1/* Copyright (c) 2003, 2007 Reiner Patommel
2   Copyright (c) 2009  Dmitry Xmelkov
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   * Redistributions of source code must retain the above copyright
9     notice, this list of conditions and the following disclaimer.
10   * Redistributions in binary form must reproduce the above copyright
11     notice, this list of conditions and the following disclaimer in
12     the documentation and/or other materials provided with the
13     distribution.
14   * Neither the name of the copyright holders nor the names of
15     contributors may be used to endorse or promote products derived
16     from this software without specific prior written permission.
17
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  POSSIBILITY OF SUCH DAMAGE.
29*/
30
31/* $Id: strtok_r.S 2191 2010-11-05 13:45:57Z arcanum $ */
32
33/** \file */
34
35/** \ingroup avr_string
36    \fn char *strtok_r(char *string, const char *delim, char **last)
37    \brief Parses string into tokens.
38
39    strtok_r parses string into tokens. The first call to strtok_r
40    should have string as its first argument. Subsequent calls should have
41    the first argument set to NULL. If a token ends with a delimiter, this
42    delimiting character is overwritten with a '\\0' and a pointer to the next
43    character is saved for the next call to strtok_r. The delimiter string
44    \p delim may be different for each call. \p last is a user allocated char*
45    pointer. It must be the same while parsing the same string. strtok_r is
46    a reentrant version of strtok().
47
48    \returns The strtok_r() function returns a pointer to the next token or
49    NULL when no more tokens are found. */
50
51#if !defined(__AVR_TINY__)
52
53#if !defined(__DOXYGEN__)
54
55#include "asmdef.h"
56
57/*  char *strtok_r (char *s, const char *delim, char **last)
58    {
59	char *p = *last;
60	const char *q;
61	char c, d;
62
63	if (!s) {
64	    if (!p) return s;		// end of string
65	    s = p;			// continue parsing
66	}
67
68	p = s;
69	for (;;) {			// skip delimeters
70	    s = p;			// space optimization (vs. s = p-1)
71	    if (!(c = *p++)) {
72		s = 0;
73		p = 0;
74		goto ret;
75	    }
76	    q = delim;
77	    do {
78		if (!(d = *q++))
79		    goto find_end;
80	    } while (d != c);
81	}
82
83      find_end:
84	do {
85	    q = delim;
86	    do {
87		d = *q++;
88		if (c == d) {
89		    *--p = 0;
90		    p++;
91		    goto ret;
92		}
93	    } while (d);
94	} while ((c = *p++) != 0);
95	p = 0;				// stop parsing
96      ret:
97	*last = p;
98	return s;
99    }
100 */
101
102#define str_lo	r24
103#define dlm_lo	r22
104#define lst_lo	r20
105#define dch	r18
106
107ENTRY strtok_r
108	X_movw	ZL, lst_lo
109	ld	XL, Z+			; X = *last
110	ld	XH, Z
111  ; check str
112	sbiw	str_lo, 0
113	brne	1f
114	sbiw	XL, 0
115	breq	.Lret			; end of string
116	X_movw	str_lo, XL		; continue parsing
117
118  ; skip delimeters
1191:	X_movw	XL, str_lo		; p = str
1202:	X_movw	str_lo, XL
121	ld	__tmp_reg__, X+
122	tst	__tmp_reg__
123	brne	3f
124	X_movw	str_lo, __tmp_reg__	; <r0,r1>
125	rjmp	.Lclr
1263:	X_movw	ZL, dlm_lo
1274:	ld	dch, Z+
128	tst	dch
129	breq	5f			; goto find
130	cp	dch, __tmp_reg__
131	brne	4b
132	rjmp	2b			; skip 1 byte
133
134  ; find new token end
1355:	X_movw	ZL, dlm_lo
1366:	ld	dch, Z+
137	cp	dch, __tmp_reg__	; __tmp_reg__ != 0
138	brne	7f
139	st	-X, __zero_reg__
140	adiw	XL, 1
141	rjmp	.Lret
1427:	tst	dch
143	brne	6b
144  ; next str byte
145	ld	__tmp_reg__, X+
146	tst	__tmp_reg__
147	brne	5b
148
149  ; stop parsing
150.Lclr:	X_movw	XL, __tmp_reg__		; <r0,r1>
151  ; save last pointer
152.Lret:	X_movw	ZL, lst_lo		; *last = X
153	st	Z+, XL
154	st	Z, XH
155	ret
156
157ENDFUNC
158
159#endif /* not __DOXYGEN__ */
160
161#endif /* !defined(__AVR_TINY__) */
162