1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin  * Glenn Fowler
25da2e3ebdSchin  * AT&T Research
26da2e3ebdSchin  *
27da2e3ebdSchin  * token stream routines
28da2e3ebdSchin  */
29da2e3ebdSchin 
30da2e3ebdSchin #include <ast.h>
31da2e3ebdSchin #include <tok.h>
32da2e3ebdSchin 
33da2e3ebdSchin #define FLG_RESTORE	01		/* restore string on close	*/
34da2e3ebdSchin #define FLG_NEWLINE	02		/* return newline token next	*/
35da2e3ebdSchin 
36da2e3ebdSchin typedef struct Tok_s			/* token stream state		*/
37da2e3ebdSchin {
38da2e3ebdSchin 	union
39da2e3ebdSchin 	{
40da2e3ebdSchin 	char*		end;		/* end ('\0') of last token	*/
41da2e3ebdSchin 	struct Tok_s*	nxt;		/* next in free list		*/
42da2e3ebdSchin 	}		ptr;
43da2e3ebdSchin 	char		chr;		/* replace *end with this	*/
44da2e3ebdSchin 	char		flg;		/* FLG_*			*/
45da2e3ebdSchin } Tok_t;
46da2e3ebdSchin 
47da2e3ebdSchin static Tok_t*		freelist;
48da2e3ebdSchin 
49da2e3ebdSchin /*
50da2e3ebdSchin  * open a new token stream on s
51da2e3ebdSchin  * if f==0 then string is not restored
52da2e3ebdSchin  */
53da2e3ebdSchin 
54da2e3ebdSchin char*
tokopen(register char * s,int f)55da2e3ebdSchin tokopen(register char* s, int f)
56da2e3ebdSchin {
57da2e3ebdSchin 	register Tok_t*	p;
58da2e3ebdSchin 
59da2e3ebdSchin 	if (p = freelist)
60da2e3ebdSchin 		freelist = freelist->ptr.nxt;
61da2e3ebdSchin 	else if (!(p = newof(0, Tok_t, 1, 0)))
62da2e3ebdSchin 		return 0;
63da2e3ebdSchin 	p->chr = *(p->ptr.end = s);
64da2e3ebdSchin 	p->flg = f ? FLG_RESTORE : 0;
65da2e3ebdSchin 	return (char*)p;
66da2e3ebdSchin }
67da2e3ebdSchin 
68da2e3ebdSchin /*
69da2e3ebdSchin  * close a token stream
70da2e3ebdSchin  * restore the string to its original state
71da2e3ebdSchin  */
72da2e3ebdSchin 
73da2e3ebdSchin void
tokclose(char * u)74da2e3ebdSchin tokclose(char* u)
75da2e3ebdSchin {
76da2e3ebdSchin 	register Tok_t*	p = (Tok_t*)u;
77da2e3ebdSchin 
78da2e3ebdSchin 	if (p->flg == FLG_RESTORE && *p->ptr.end != p->chr)
79da2e3ebdSchin 		*p->ptr.end = p->chr;
80da2e3ebdSchin 	p->ptr.nxt = freelist;
81da2e3ebdSchin 	freelist = p;
82da2e3ebdSchin }
83da2e3ebdSchin 
84da2e3ebdSchin /*
85da2e3ebdSchin  * return next space separated token
86da2e3ebdSchin  * "\n" is returned as a token
87da2e3ebdSchin  * 0 returned when no tokens remain
88da2e3ebdSchin  * "..." and '...' quotes are honored with \ escapes
89da2e3ebdSchin  */
90da2e3ebdSchin 
91da2e3ebdSchin char*
tokread(char * u)92da2e3ebdSchin tokread(char* u)
93da2e3ebdSchin {
94da2e3ebdSchin 	register Tok_t*	p = (Tok_t*)u;
95da2e3ebdSchin 	register char*	s;
96da2e3ebdSchin 	register char*	r;
97da2e3ebdSchin 	register int	q;
98da2e3ebdSchin 	register int	c;
99da2e3ebdSchin 
100da2e3ebdSchin 	/*
101da2e3ebdSchin 	 * restore string on each call
102da2e3ebdSchin 	 */
103da2e3ebdSchin 
104da2e3ebdSchin 	if (!p->chr)
105da2e3ebdSchin 		return 0;
106da2e3ebdSchin 	s = p->ptr.end;
107da2e3ebdSchin 	switch (p->flg)
108da2e3ebdSchin 	{
109da2e3ebdSchin 	case FLG_NEWLINE:
110da2e3ebdSchin 		p->flg = 0;
111da2e3ebdSchin 		return "\n";
112da2e3ebdSchin 	case FLG_RESTORE:
113da2e3ebdSchin 		if (*s != p->chr)
114da2e3ebdSchin 			*s = p->chr;
115da2e3ebdSchin 		break;
116da2e3ebdSchin 	default:
117da2e3ebdSchin 		if (!*s)
118da2e3ebdSchin 			s++;
119da2e3ebdSchin 		break;
120da2e3ebdSchin 	}
121da2e3ebdSchin 
122da2e3ebdSchin 	/*
123da2e3ebdSchin 	 * skip leading space
124da2e3ebdSchin 	 */
125da2e3ebdSchin 
126da2e3ebdSchin 	while (*s == ' ' || *s == '\t')
127da2e3ebdSchin 		s++;
128da2e3ebdSchin 	if (!*s)
129da2e3ebdSchin 	{
130da2e3ebdSchin 		p->ptr.end = s;
131da2e3ebdSchin 		p->chr = 0;
132da2e3ebdSchin 		return 0;
133da2e3ebdSchin 	}
134da2e3ebdSchin 
135da2e3ebdSchin 	/*
136da2e3ebdSchin 	 * find the end of this token
137da2e3ebdSchin 	 */
138da2e3ebdSchin 
139da2e3ebdSchin 	r = s;
140da2e3ebdSchin 	q = 0;
141da2e3ebdSchin 	for (;;)
142da2e3ebdSchin 		switch (c = *r++)
143da2e3ebdSchin 		{
144da2e3ebdSchin 		case '\n':
145da2e3ebdSchin 			if (!q)
146da2e3ebdSchin 			{
147da2e3ebdSchin 				if (s == (r - 1))
148da2e3ebdSchin 				{
149da2e3ebdSchin 					if (!p->flg)
150da2e3ebdSchin 					{
151da2e3ebdSchin 						p->ptr.end = r;
152da2e3ebdSchin 						return "\n";
153da2e3ebdSchin 					}
154da2e3ebdSchin 					r++;
155da2e3ebdSchin 				}
156da2e3ebdSchin 				else if (!p->flg)
157da2e3ebdSchin 					p->flg = FLG_NEWLINE;
158da2e3ebdSchin 			}
159da2e3ebdSchin 			/*FALLTHROUGH*/
160da2e3ebdSchin 		case ' ':
161da2e3ebdSchin 		case '\t':
162da2e3ebdSchin 			if (q)
163da2e3ebdSchin 				break;
164da2e3ebdSchin 			/*FALLTHROUGH*/
165da2e3ebdSchin 		case 0:
166da2e3ebdSchin 			if (s == --r)
167da2e3ebdSchin 			{
168da2e3ebdSchin 				p->ptr.end = r;
169da2e3ebdSchin 				p->chr = 0;
170da2e3ebdSchin 			}
171da2e3ebdSchin 			else
172da2e3ebdSchin 			{
173da2e3ebdSchin 				p->chr = *(p->ptr.end = r);
174da2e3ebdSchin 				if (*r)
175da2e3ebdSchin 					*r = 0;
176da2e3ebdSchin 			}
177da2e3ebdSchin 			return s;
178da2e3ebdSchin 		case '\\':
179da2e3ebdSchin 			if (*r)
180da2e3ebdSchin 				r++;
181da2e3ebdSchin 			break;
182da2e3ebdSchin 		case '"':
183da2e3ebdSchin 		case '\'':
184da2e3ebdSchin 			if (c == q)
185da2e3ebdSchin 				q = 0;
186da2e3ebdSchin 			else if (!q)
187da2e3ebdSchin 				q = c;
188da2e3ebdSchin 			break;
189da2e3ebdSchin 		}
190da2e3ebdSchin }
191