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 */
fcfopen(register Sfio_t * f)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 */
fcfill(void)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 */
fcclose(void)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 */
fcnotify(void (* fun)(Sfio_t *,const char *,int,void *),void * context)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
fcsave(Fcin_t * fp)1424887Schin extern void fcsave(Fcin_t *fp)
1434887Schin {
1444887Schin *fp = _Fcin;
1454887Schin }
1464887Schin
1474887Schin #undef fcrestore
fcrestore(Fcin_t * fp)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
fcmbstate(const char * state,int * s,int * len)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