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