xref: /onnv-gate/usr/src/lib/libast/common/string/tok.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * Glenn Fowler
254887Schin  * AT&T Research
264887Schin  *
274887Schin  * token stream routines
284887Schin  */
294887Schin 
304887Schin #include <ast.h>
314887Schin #include <tok.h>
324887Schin 
334887Schin #define FLG_RESTORE	01		/* restore string on close	*/
344887Schin #define FLG_NEWLINE	02		/* return newline token next	*/
354887Schin 
364887Schin typedef struct Tok_s			/* token stream state		*/
374887Schin {
384887Schin 	union
394887Schin 	{
404887Schin 	char*		end;		/* end ('\0') of last token	*/
414887Schin 	struct Tok_s*	nxt;		/* next in free list		*/
424887Schin 	}		ptr;
434887Schin 	char		chr;		/* replace *end with this	*/
444887Schin 	char		flg;		/* FLG_*			*/
454887Schin } Tok_t;
464887Schin 
474887Schin static Tok_t*		freelist;
484887Schin 
494887Schin /*
504887Schin  * open a new token stream on s
514887Schin  * if f==0 then string is not restored
524887Schin  */
534887Schin 
544887Schin char*
tokopen(register char * s,int f)554887Schin tokopen(register char* s, int f)
564887Schin {
574887Schin 	register Tok_t*	p;
584887Schin 
594887Schin 	if (p = freelist)
604887Schin 		freelist = freelist->ptr.nxt;
614887Schin 	else if (!(p = newof(0, Tok_t, 1, 0)))
624887Schin 		return 0;
634887Schin 	p->chr = *(p->ptr.end = s);
644887Schin 	p->flg = f ? FLG_RESTORE : 0;
654887Schin 	return (char*)p;
664887Schin }
674887Schin 
684887Schin /*
694887Schin  * close a token stream
704887Schin  * restore the string to its original state
714887Schin  */
724887Schin 
734887Schin void
tokclose(char * u)744887Schin tokclose(char* u)
754887Schin {
764887Schin 	register Tok_t*	p = (Tok_t*)u;
774887Schin 
784887Schin 	if (p->flg == FLG_RESTORE && *p->ptr.end != p->chr)
794887Schin 		*p->ptr.end = p->chr;
804887Schin 	p->ptr.nxt = freelist;
814887Schin 	freelist = p;
824887Schin }
834887Schin 
844887Schin /*
854887Schin  * return next space separated token
864887Schin  * "\n" is returned as a token
874887Schin  * 0 returned when no tokens remain
884887Schin  * "..." and '...' quotes are honored with \ escapes
894887Schin  */
904887Schin 
914887Schin char*
tokread(char * u)924887Schin tokread(char* u)
934887Schin {
944887Schin 	register Tok_t*	p = (Tok_t*)u;
954887Schin 	register char*	s;
964887Schin 	register char*	r;
974887Schin 	register int	q;
984887Schin 	register int	c;
994887Schin 
1004887Schin 	/*
1014887Schin 	 * restore string on each call
1024887Schin 	 */
1034887Schin 
1044887Schin 	if (!p->chr)
1054887Schin 		return 0;
1064887Schin 	s = p->ptr.end;
1074887Schin 	switch (p->flg)
1084887Schin 	{
1094887Schin 	case FLG_NEWLINE:
1104887Schin 		p->flg = 0;
1114887Schin 		return "\n";
1124887Schin 	case FLG_RESTORE:
1134887Schin 		if (*s != p->chr)
1144887Schin 			*s = p->chr;
1154887Schin 		break;
1164887Schin 	default:
1174887Schin 		if (!*s)
1184887Schin 			s++;
1194887Schin 		break;
1204887Schin 	}
1214887Schin 
1224887Schin 	/*
1234887Schin 	 * skip leading space
1244887Schin 	 */
1254887Schin 
1264887Schin 	while (*s == ' ' || *s == '\t')
1274887Schin 		s++;
1284887Schin 	if (!*s)
1294887Schin 	{
1304887Schin 		p->ptr.end = s;
1314887Schin 		p->chr = 0;
1324887Schin 		return 0;
1334887Schin 	}
1344887Schin 
1354887Schin 	/*
1364887Schin 	 * find the end of this token
1374887Schin 	 */
1384887Schin 
1394887Schin 	r = s;
1404887Schin 	q = 0;
1414887Schin 	for (;;)
1424887Schin 		switch (c = *r++)
1434887Schin 		{
1444887Schin 		case '\n':
1454887Schin 			if (!q)
1464887Schin 			{
1474887Schin 				if (s == (r - 1))
1484887Schin 				{
1494887Schin 					if (!p->flg)
1504887Schin 					{
1514887Schin 						p->ptr.end = r;
1524887Schin 						return "\n";
1534887Schin 					}
1544887Schin 					r++;
1554887Schin 				}
1564887Schin 				else if (!p->flg)
1574887Schin 					p->flg = FLG_NEWLINE;
1584887Schin 			}
1594887Schin 			/*FALLTHROUGH*/
1604887Schin 		case ' ':
1614887Schin 		case '\t':
1624887Schin 			if (q)
1634887Schin 				break;
1644887Schin 			/*FALLTHROUGH*/
1654887Schin 		case 0:
1664887Schin 			if (s == --r)
1674887Schin 			{
1684887Schin 				p->ptr.end = r;
1694887Schin 				p->chr = 0;
1704887Schin 			}
1714887Schin 			else
1724887Schin 			{
1734887Schin 				p->chr = *(p->ptr.end = r);
1744887Schin 				if (*r)
1754887Schin 					*r = 0;
1764887Schin 			}
1774887Schin 			return s;
1784887Schin 		case '\\':
1794887Schin 			if (*r)
1804887Schin 				r++;
1814887Schin 			break;
1824887Schin 		case '"':
1834887Schin 		case '\'':
1844887Schin 			if (c == q)
1854887Schin 				q = 0;
1864887Schin 			else if (!q)
1874887Schin 				q = c;
1884887Schin 			break;
1894887Schin 		}
1904887Schin }
191