xref: /onnv-gate/usr/src/lib/libshell/common/sh/fcin.c (revision 12068:08a39a083754)
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