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