xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/fcin.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1982-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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  */
fcfopen(register Sfio_t * f)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  */
fcfill(void)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,_Fcin.context);
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  */
fcclose(void)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  */
fcnotify(void (* fun)(Sfio_t *,const char *,int,void *),void * context)131 void fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context)
132 {
133 	_Fcin.fcfun = fun;
134 	_Fcin.context = context;
135 }
136 
137 #ifdef __EXPORT__
138 #   define extern __EXPORT__
139 #endif
140 
141 #undef fcsave
fcsave(Fcin_t * fp)142 extern void fcsave(Fcin_t *fp)
143 {
144 	*fp = _Fcin;
145 }
146 
147 #undef fcrestore
fcrestore(Fcin_t * fp)148 extern void fcrestore(Fcin_t *fp)
149 {
150 	_Fcin = *fp;
151 }
152 
153 /* for testing purposes with small buffers */
154 #if defined(IOBSIZE) && (IOBSIZE < 2*MB_LEN_MAX)
155 #   undef MB_LEN_MAX
156 #   define MB_LEN_MAX	(IOBSIZE/2)
157 #endif
158 
159 struct Extra
160 {
161 	unsigned char	buff[2*MB_LEN_MAX];
162 	unsigned char	*next;
163 };
164 
_fcmbget(short * len)165 int _fcmbget(short *len)
166 {
167 	static struct Extra	extra;
168 	register int		i, c, n;
169 	if(_Fcin.fcleft)
170 	{
171 		if((c = mbsize(extra.next)) < 0)
172 			c = 1;
173 		if((_Fcin.fcleft -= c) <=0)
174 		{
175 			_Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft;
176 			_Fcin.fcleft = 0;
177 		}
178 		*len = c;
179 		if(c==1)
180 			c = *extra.next++;
181 		else if(c==0)
182 			_Fcin.fcleft = 0;
183 		else
184 			c = mbchar(extra.next);
185 		return(c);
186 	}
187 	switch(*len = mbsize(_Fcin.fcptr))
188 	{
189 	    case -1:
190 		if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX)
191 		{
192 			memcpy(extra.buff, _Fcin.fcptr, n);
193 			_Fcin.fcptr = _Fcin.fclast;
194 			for(i=n; i < MB_LEN_MAX+n; i++)
195 			{
196 				if((extra.buff[i] = fcgetc(c))==0)
197 					break;
198 			}
199 			_Fcin.fcleft = n;
200 			extra.next = extra.buff;
201 			return(fcmbget(len));
202 		}
203 		*len = 1;
204 		/* fall through */
205 	    case 0:
206 	    case 1:
207 		c=fcget();
208 		break;
209 	    default:
210 		c = mbchar(_Fcin.fcptr);
211 	}
212 	return(c);
213 }
214 
215