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