1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 77c2fbfb3SApril Chin * by AT&T Intellectual Property * 8da2e3ebdSchin * * 9da2e3ebdSchin * A copy of the License is available at * 10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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)55da2e3ebdSchintokopen(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)74da2e3ebdSchintokclose(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)92da2e3ebdSchintokread(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