xref: /titanic_50/usr/src/lib/libshell/common/sh/fcin.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1982-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 *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  *   Routines to implement fast character input
23da2e3ebdSchin  *
24da2e3ebdSchin  *   David Korn
25da2e3ebdSchin  *   AT&T Labs
26da2e3ebdSchin  *
27da2e3ebdSchin  */
28da2e3ebdSchin 
29da2e3ebdSchin #include	<ast.h>
30da2e3ebdSchin #include	<sfio.h>
31da2e3ebdSchin #include	<error.h>
32da2e3ebdSchin #include	<fcin.h>
33da2e3ebdSchin 
34da2e3ebdSchin Fcin_t _Fcin = {0};
35da2e3ebdSchin 
36da2e3ebdSchin /*
37da2e3ebdSchin  * open stream <f> for fast character input
38da2e3ebdSchin  */
fcfopen(register Sfio_t * f)39da2e3ebdSchin int	fcfopen(register Sfio_t* f)
40da2e3ebdSchin {
41da2e3ebdSchin 	register int	n;
42da2e3ebdSchin 	char		*buff;
43da2e3ebdSchin 	Fcin_t		save;
44da2e3ebdSchin 	errno = 0;
45da2e3ebdSchin 	_Fcin.fcbuff = _Fcin.fcptr;
46da2e3ebdSchin 	_Fcin._fcfile = f;
47da2e3ebdSchin 	fcsave(&save);
48da2e3ebdSchin 	if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR)))
49da2e3ebdSchin 	{
50da2e3ebdSchin 		fcrestore(&save);
51da2e3ebdSchin 		_Fcin.fcchar = 0;
52da2e3ebdSchin 		_Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar;
53da2e3ebdSchin 		_Fcin.fclast = 0;
54da2e3ebdSchin 		_Fcin._fcfile = (Sfio_t*)0;
55da2e3ebdSchin 		return(EOF);
56da2e3ebdSchin 	}
57da2e3ebdSchin 	n = sfvalue(f);
58da2e3ebdSchin 	fcrestore(&save);
59da2e3ebdSchin 	sfread(f,buff,0);
60da2e3ebdSchin 	_Fcin.fcoff = sftell(f);;
61da2e3ebdSchin 	buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR);
62da2e3ebdSchin 	_Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n;
63da2e3ebdSchin 	if(sffileno(f) >= 0)
64da2e3ebdSchin 		*_Fcin.fclast = 0;
65da2e3ebdSchin 	return(n);
66da2e3ebdSchin }
67da2e3ebdSchin 
68da2e3ebdSchin 
69da2e3ebdSchin /*
70da2e3ebdSchin  * With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and
71da2e3ebdSchin  * If _Fcin.fclast!=0, performs an sfreserve() for the next buffer.
72da2e3ebdSchin  * If a notify function has been set, it is called
73da2e3ebdSchin  * If last is non-zero, and the stream is a file, 0 is returned when
74da2e3ebdSchin  * the previous character is a 0 byte.
75da2e3ebdSchin  */
fcfill(void)76da2e3ebdSchin int	fcfill(void)
77da2e3ebdSchin {
78da2e3ebdSchin 	register int		n;
79da2e3ebdSchin 	register Sfio_t	*f;
80da2e3ebdSchin 	register unsigned char	*last=_Fcin.fclast, *ptr=_Fcin.fcptr;
81da2e3ebdSchin 	if(!(f=fcfile()))
82da2e3ebdSchin 	{
83da2e3ebdSchin 		/* see whether pointer has passed null byte */
84da2e3ebdSchin 		if(ptr>_Fcin.fcbuff && *--ptr==0)
85da2e3ebdSchin 			_Fcin.fcptr=ptr;
86da2e3ebdSchin 		else
87da2e3ebdSchin 			_Fcin.fcoff = 0;
88da2e3ebdSchin 		return(0);
89da2e3ebdSchin 	}
90da2e3ebdSchin 	if(last)
91da2e3ebdSchin 	{
92da2e3ebdSchin 		if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0)
93da2e3ebdSchin 			return(0);
94da2e3ebdSchin 		if(_Fcin.fcchar)
95da2e3ebdSchin 			*last = _Fcin.fcchar;
96da2e3ebdSchin 		if(ptr > last)
97da2e3ebdSchin 			_Fcin.fcptr = ptr = last;
98da2e3ebdSchin 	}
99da2e3ebdSchin 	if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun)
1007c2fbfb3SApril Chin 		(*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n,_Fcin.context);
101da2e3ebdSchin 	sfread(f, (char*)_Fcin.fcbuff, n);
102da2e3ebdSchin 	_Fcin.fcoff +=n;
103da2e3ebdSchin 	_Fcin._fcfile = 0;
104da2e3ebdSchin 	if(!last)
105da2e3ebdSchin 		return(0);
106da2e3ebdSchin 	else if(fcfopen(f) < 0)
107da2e3ebdSchin 		return(EOF);
108da2e3ebdSchin 	return(*_Fcin.fcptr++);
109da2e3ebdSchin }
110da2e3ebdSchin 
111da2e3ebdSchin /*
112da2e3ebdSchin  * Synchronize and close the current stream
113da2e3ebdSchin  */
fcclose(void)114da2e3ebdSchin int fcclose(void)
115da2e3ebdSchin {
116da2e3ebdSchin 	register unsigned char *ptr;
117da2e3ebdSchin 	if(_Fcin.fclast==0)
118da2e3ebdSchin 		return(0);
119da2e3ebdSchin 	if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0)
120da2e3ebdSchin 		_Fcin.fcptr--;
121da2e3ebdSchin 	if(_Fcin.fcchar)
122da2e3ebdSchin 		*_Fcin.fclast = _Fcin.fcchar;
123da2e3ebdSchin 	_Fcin.fclast = 0;
124da2e3ebdSchin 	_Fcin.fcleft = 0;
125da2e3ebdSchin 	return(fcfill());
126da2e3ebdSchin }
127da2e3ebdSchin 
128da2e3ebdSchin /*
129da2e3ebdSchin  * Set the notify function that is called for each fcfill()
130da2e3ebdSchin  */
fcnotify(void (* fun)(Sfio_t *,const char *,int,void *),void * context)1317c2fbfb3SApril Chin void fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context)
132da2e3ebdSchin {
133da2e3ebdSchin 	_Fcin.fcfun = fun;
1347c2fbfb3SApril Chin 	_Fcin.context = context;
135da2e3ebdSchin }
136da2e3ebdSchin 
137da2e3ebdSchin #ifdef __EXPORT__
138da2e3ebdSchin #   define extern __EXPORT__
139da2e3ebdSchin #endif
140da2e3ebdSchin 
141da2e3ebdSchin #undef fcsave
fcsave(Fcin_t * fp)142da2e3ebdSchin extern void fcsave(Fcin_t *fp)
143da2e3ebdSchin {
144da2e3ebdSchin 	*fp = _Fcin;
145da2e3ebdSchin }
146da2e3ebdSchin 
147da2e3ebdSchin #undef fcrestore
fcrestore(Fcin_t * fp)148da2e3ebdSchin extern void fcrestore(Fcin_t *fp)
149da2e3ebdSchin {
150da2e3ebdSchin 	_Fcin = *fp;
151da2e3ebdSchin }
152da2e3ebdSchin 
153da2e3ebdSchin struct Extra
154da2e3ebdSchin {
155da2e3ebdSchin 	unsigned char	buff[2*MB_LEN_MAX];
156da2e3ebdSchin 	unsigned char	*next;
157da2e3ebdSchin };
158da2e3ebdSchin 
fcmbstate(const char * state,int * s,int * len)159da2e3ebdSchin int fcmbstate(const char *state, int *s, int *len)
160da2e3ebdSchin {
161da2e3ebdSchin 	static struct Extra	extra;
162da2e3ebdSchin 	register int		i, c, n;
163da2e3ebdSchin 	if(_Fcin.fcleft)
164da2e3ebdSchin 	{
165da2e3ebdSchin 		if((c = mbsize(extra.next)) < 0)
166da2e3ebdSchin 			c = 1;
167da2e3ebdSchin 		if((_Fcin.fcleft -= c) <=0)
168da2e3ebdSchin 		{
169da2e3ebdSchin 			_Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft;
170da2e3ebdSchin 			_Fcin.fcleft = 0;
171da2e3ebdSchin 		}
172da2e3ebdSchin 		*len = c;
173da2e3ebdSchin 		if(c==1)
174da2e3ebdSchin 			*s = state[*extra.next++];
175da2e3ebdSchin 		else if(c==0)
176da2e3ebdSchin 			_Fcin.fcleft = 0;
177da2e3ebdSchin 		else
178da2e3ebdSchin 		{
179da2e3ebdSchin 			c = mbchar(extra.next);
180da2e3ebdSchin 			*s = state['a'];
181da2e3ebdSchin 		}
182da2e3ebdSchin 		return(c);
183da2e3ebdSchin 	}
184da2e3ebdSchin 	switch(*len = mbsize(_Fcin.fcptr))
185da2e3ebdSchin 	{
186da2e3ebdSchin 	    case -1:
187da2e3ebdSchin 		if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX)
188da2e3ebdSchin 		{
189*3e14f97fSRoger A. Faulkner 			memcpy(extra.buff, _Fcin.fcptr, n);
190da2e3ebdSchin 			_Fcin.fcptr = _Fcin.fclast;
191da2e3ebdSchin 			for(i=n; i < MB_LEN_MAX+n; i++)
192da2e3ebdSchin 			{
193da2e3ebdSchin 				if((extra.buff[i] = fcgetc(c))==0)
194da2e3ebdSchin 					break;
195da2e3ebdSchin 			}
196da2e3ebdSchin 			_Fcin.fcleft = n;
197da2e3ebdSchin 			extra.next = extra.buff;
198da2e3ebdSchin 			return(fcmbstate(state,s,len));
199da2e3ebdSchin 		}
200da2e3ebdSchin 		*len = 1;
201da2e3ebdSchin 		/* fall through */
202da2e3ebdSchin 	    case 0:
203da2e3ebdSchin 	    case 1:
204da2e3ebdSchin 		*s = state[c=fcget()];
205da2e3ebdSchin 		break;
206da2e3ebdSchin 	    default:
207da2e3ebdSchin 		c = mbchar(_Fcin.fcptr);
208da2e3ebdSchin 		*s = state['a'];
209da2e3ebdSchin 	}
210da2e3ebdSchin 	return(c);
211da2e3ebdSchin }
212da2e3ebdSchin 
213