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)554887Schintokopen(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)744887Schintokclose(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)924887Schintokread(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