14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-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 * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * Routines to implement fast character input 234887Schin * 244887Schin * David Korn 254887Schin * AT&T Labs 264887Schin * 274887Schin */ 284887Schin 294887Schin #include <ast.h> 304887Schin #include <sfio.h> 314887Schin #include <error.h> 324887Schin #include <fcin.h> 334887Schin 344887Schin Fcin_t _Fcin = {0}; 354887Schin 364887Schin /* 374887Schin * open stream <f> for fast character input 384887Schin */ 394887Schin int fcfopen(register Sfio_t* f) 404887Schin { 414887Schin register int n; 424887Schin char *buff; 434887Schin Fcin_t save; 444887Schin errno = 0; 454887Schin _Fcin.fcbuff = _Fcin.fcptr; 464887Schin _Fcin._fcfile = f; 474887Schin fcsave(&save); 484887Schin if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR))) 494887Schin { 504887Schin fcrestore(&save); 514887Schin _Fcin.fcchar = 0; 524887Schin _Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar; 534887Schin _Fcin.fclast = 0; 544887Schin _Fcin._fcfile = (Sfio_t*)0; 554887Schin return(EOF); 564887Schin } 574887Schin n = sfvalue(f); 584887Schin fcrestore(&save); 594887Schin sfread(f,buff,0); 604887Schin _Fcin.fcoff = sftell(f);; 614887Schin buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR); 624887Schin _Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n; 634887Schin if(sffileno(f) >= 0) 644887Schin *_Fcin.fclast = 0; 654887Schin return(n); 664887Schin } 674887Schin 684887Schin 694887Schin /* 704887Schin * With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and 714887Schin * If _Fcin.fclast!=0, performs an sfreserve() for the next buffer. 724887Schin * If a notify function has been set, it is called 734887Schin * If last is non-zero, and the stream is a file, 0 is returned when 744887Schin * the previous character is a 0 byte. 754887Schin */ 764887Schin int fcfill(void) 774887Schin { 784887Schin register int n; 794887Schin register Sfio_t *f; 804887Schin register unsigned char *last=_Fcin.fclast, *ptr=_Fcin.fcptr; 814887Schin if(!(f=fcfile())) 824887Schin { 834887Schin /* see whether pointer has passed null byte */ 844887Schin if(ptr>_Fcin.fcbuff && *--ptr==0) 854887Schin _Fcin.fcptr=ptr; 864887Schin else 874887Schin _Fcin.fcoff = 0; 884887Schin return(0); 894887Schin } 904887Schin if(last) 914887Schin { 924887Schin if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0) 934887Schin return(0); 944887Schin if(_Fcin.fcchar) 954887Schin *last = _Fcin.fcchar; 964887Schin if(ptr > last) 974887Schin _Fcin.fcptr = ptr = last; 984887Schin } 994887Schin if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun) 1008462SApril.Chin@Sun.COM (*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n,_Fcin.context); 1014887Schin sfread(f, (char*)_Fcin.fcbuff, n); 1024887Schin _Fcin.fcoff +=n; 1034887Schin _Fcin._fcfile = 0; 1044887Schin if(!last) 1054887Schin return(0); 1064887Schin else if(fcfopen(f) < 0) 1074887Schin return(EOF); 1084887Schin return(*_Fcin.fcptr++); 1094887Schin } 1104887Schin 1114887Schin /* 1124887Schin * Synchronize and close the current stream 1134887Schin */ 1144887Schin int fcclose(void) 1154887Schin { 1164887Schin register unsigned char *ptr; 1174887Schin if(_Fcin.fclast==0) 1184887Schin return(0); 1194887Schin if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0) 1204887Schin _Fcin.fcptr--; 1214887Schin if(_Fcin.fcchar) 1224887Schin *_Fcin.fclast = _Fcin.fcchar; 1234887Schin _Fcin.fclast = 0; 1244887Schin _Fcin.fcleft = 0; 1254887Schin return(fcfill()); 1264887Schin } 1274887Schin 1284887Schin /* 1294887Schin * Set the notify function that is called for each fcfill() 1304887Schin */ 1318462SApril.Chin@Sun.COM void fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context) 1324887Schin { 1334887Schin _Fcin.fcfun = fun; 1348462SApril.Chin@Sun.COM _Fcin.context = context; 1354887Schin } 1364887Schin 1374887Schin #ifdef __EXPORT__ 1384887Schin # define extern __EXPORT__ 1394887Schin #endif 1404887Schin 1414887Schin #undef fcsave 1424887Schin extern void fcsave(Fcin_t *fp) 1434887Schin { 1444887Schin *fp = _Fcin; 1454887Schin } 1464887Schin 1474887Schin #undef fcrestore 1484887Schin extern void fcrestore(Fcin_t *fp) 1494887Schin { 1504887Schin _Fcin = *fp; 1514887Schin } 1524887Schin 1534887Schin struct Extra 1544887Schin { 1554887Schin unsigned char buff[2*MB_LEN_MAX]; 1564887Schin unsigned char *next; 1574887Schin }; 1584887Schin 1594887Schin int fcmbstate(const char *state, int *s, int *len) 1604887Schin { 1614887Schin static struct Extra extra; 1624887Schin register int i, c, n; 1634887Schin if(_Fcin.fcleft) 1644887Schin { 1654887Schin if((c = mbsize(extra.next)) < 0) 1664887Schin c = 1; 1674887Schin if((_Fcin.fcleft -= c) <=0) 1684887Schin { 1694887Schin _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft; 1704887Schin _Fcin.fcleft = 0; 1714887Schin } 1724887Schin *len = c; 1734887Schin if(c==1) 1744887Schin *s = state[*extra.next++]; 1754887Schin else if(c==0) 1764887Schin _Fcin.fcleft = 0; 1774887Schin else 1784887Schin { 1794887Schin c = mbchar(extra.next); 1804887Schin *s = state['a']; 1814887Schin } 1824887Schin return(c); 1834887Schin } 1844887Schin switch(*len = mbsize(_Fcin.fcptr)) 1854887Schin { 1864887Schin case -1: 1874887Schin if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX) 1884887Schin { 189*12068SRoger.Faulkner@Oracle.COM memcpy(extra.buff, _Fcin.fcptr, n); 1904887Schin _Fcin.fcptr = _Fcin.fclast; 1914887Schin for(i=n; i < MB_LEN_MAX+n; i++) 1924887Schin { 1934887Schin if((extra.buff[i] = fcgetc(c))==0) 1944887Schin break; 1954887Schin } 1964887Schin _Fcin.fcleft = n; 1974887Schin extra.next = extra.buff; 1984887Schin return(fcmbstate(state,s,len)); 1994887Schin } 2004887Schin *len = 1; 2014887Schin /* fall through */ 2024887Schin case 0: 2034887Schin case 1: 2044887Schin *s = state[c=fcget()]; 2054887Schin break; 2064887Schin default: 2074887Schin c = mbchar(_Fcin.fcptr); 2084887Schin *s = state['a']; 2094887Schin } 2104887Schin return(c); 2114887Schin } 2124887Schin 213