da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1982-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Routines to implement fast character input
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sfio.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <error.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <fcin.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinFcin_t _Fcin = {0};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * open stream <f> for fast character input
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint fcfopen(register Sfio_t* f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *buff;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Fcin_t save;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcbuff = _Fcin.fcptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin._fcfile = f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcsave(&save);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcrestore(&save);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcchar = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fclast = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin._fcfile = (Sfio_t*)0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(EOF);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sfvalue(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcrestore(&save);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfread(f,buff,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcoff = sftell(f);;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sffileno(f) >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *_Fcin.fclast = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If _Fcin.fclast!=0, performs an sfreserve() for the next buffer.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If a notify function has been set, it is called
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If last is non-zero, and the stream is a file, 0 is returned when
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the previous character is a 0 byte.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint fcfill(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Sfio_t *f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *last=_Fcin.fclast, *ptr=_Fcin.fcptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(f=fcfile()))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see whether pointer has passed null byte */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ptr>_Fcin.fcbuff && *--ptr==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcptr=ptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcoff = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(last)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Fcin.fcchar)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *last = _Fcin.fcchar;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ptr > last)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcptr = ptr = last;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n,_Fcin.context);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfread(f, (char*)_Fcin.fcbuff, n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcoff +=n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin._fcfile = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!last)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(fcfopen(f) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(EOF);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(*_Fcin.fcptr++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Synchronize and close the current stream
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint fcclose(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *ptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Fcin.fclast==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcptr--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Fcin.fcchar)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *_Fcin.fclast = _Fcin.fcchar;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fclast = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcleft = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(fcfill());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Set the notify function that is called for each fcfill()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinvoid fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcfun = fun;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin _Fcin.context = context;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef __EXPORT__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define extern __EXPORT__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef fcsave
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void fcsave(Fcin_t *fp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fp = _Fcin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef fcrestore
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void fcrestore(Fcin_t *fp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin = *fp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct Extra
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char buff[2*MB_LEN_MAX];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char *next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint fcmbstate(const char *state, int *s, int *len)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct Extra extra;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int i, c, n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Fcin.fcleft)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((c = mbsize(extra.next)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((_Fcin.fcleft -= c) <=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcleft = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *len = c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(c==1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = state[*extra.next++];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcleft = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = mbchar(extra.next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = state['a'];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch(*len = mbsize(_Fcin.fcptr))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case -1:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner memcpy(extra.buff, _Fcin.fcptr, n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcptr = _Fcin.fclast;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(i=n; i < MB_LEN_MAX+n; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((extra.buff[i] = fcgetc(c))==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Fcin.fcleft = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extra.next = extra.buff;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(fcmbstate(state,s,len));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *len = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* fall through */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 1:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = state[c=fcget()];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = mbchar(_Fcin.fcptr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = state['a'];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin