summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/sh/fcin.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libshell/common/sh/fcin.c')
-rw-r--r--usr/src/lib/libshell/common/sh/fcin.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/usr/src/lib/libshell/common/sh/fcin.c b/usr/src/lib/libshell/common/sh/fcin.c
new file mode 100644
index 0000000000..aea98364f5
--- /dev/null
+++ b/usr/src/lib/libshell/common/sh/fcin.c
@@ -0,0 +1,211 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Routines to implement fast character input
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include <fcin.h>
+
+Fcin_t _Fcin = {0};
+
+/*
+ * open stream <f> for fast character input
+ */
+int fcfopen(register Sfio_t* f)
+{
+ register int n;
+ char *buff;
+ Fcin_t save;
+ errno = 0;
+ _Fcin.fcbuff = _Fcin.fcptr;
+ _Fcin._fcfile = f;
+ fcsave(&save);
+ if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR)))
+ {
+ fcrestore(&save);
+ _Fcin.fcchar = 0;
+ _Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar;
+ _Fcin.fclast = 0;
+ _Fcin._fcfile = (Sfio_t*)0;
+ return(EOF);
+ }
+ n = sfvalue(f);
+ fcrestore(&save);
+ sfread(f,buff,0);
+ _Fcin.fcoff = sftell(f);;
+ buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR);
+ _Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n;
+ if(sffileno(f) >= 0)
+ *_Fcin.fclast = 0;
+ return(n);
+}
+
+
+/*
+ * With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and
+ * If _Fcin.fclast!=0, performs an sfreserve() for the next buffer.
+ * If a notify function has been set, it is called
+ * If last is non-zero, and the stream is a file, 0 is returned when
+ * the previous character is a 0 byte.
+ */
+int fcfill(void)
+{
+ register int n;
+ register Sfio_t *f;
+ register unsigned char *last=_Fcin.fclast, *ptr=_Fcin.fcptr;
+ if(!(f=fcfile()))
+ {
+ /* see whether pointer has passed null byte */
+ if(ptr>_Fcin.fcbuff && *--ptr==0)
+ _Fcin.fcptr=ptr;
+ else
+ _Fcin.fcoff = 0;
+ return(0);
+ }
+ if(last)
+ {
+ if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0)
+ return(0);
+ if(_Fcin.fcchar)
+ *last = _Fcin.fcchar;
+ if(ptr > last)
+ _Fcin.fcptr = ptr = last;
+ }
+ if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun)
+ (*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n);
+ sfread(f, (char*)_Fcin.fcbuff, n);
+ _Fcin.fcoff +=n;
+ _Fcin._fcfile = 0;
+ if(!last)
+ return(0);
+ else if(fcfopen(f) < 0)
+ return(EOF);
+ return(*_Fcin.fcptr++);
+}
+
+/*
+ * Synchronize and close the current stream
+ */
+int fcclose(void)
+{
+ register unsigned char *ptr;
+ if(_Fcin.fclast==0)
+ return(0);
+ if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0)
+ _Fcin.fcptr--;
+ if(_Fcin.fcchar)
+ *_Fcin.fclast = _Fcin.fcchar;
+ _Fcin.fclast = 0;
+ _Fcin.fcleft = 0;
+ return(fcfill());
+}
+
+/*
+ * Set the notify function that is called for each fcfill()
+ */
+void fcnotify(void (*fun)(Sfio_t*,const char*,int))
+{
+ _Fcin.fcfun = fun;
+}
+
+#ifdef __EXPORT__
+# define extern __EXPORT__
+#endif
+
+#undef fcsave
+extern void fcsave(Fcin_t *fp)
+{
+ *fp = _Fcin;
+}
+
+#undef fcrestore
+extern void fcrestore(Fcin_t *fp)
+{
+ _Fcin = *fp;
+}
+
+struct Extra
+{
+ unsigned char buff[2*MB_LEN_MAX];
+ unsigned char *next;
+};
+
+int fcmbstate(const char *state, int *s, int *len)
+{
+ static struct Extra extra;
+ register int i, c, n;
+ if(_Fcin.fcleft)
+ {
+ if((c = mbsize(extra.next)) < 0)
+ c = 1;
+ if((_Fcin.fcleft -= c) <=0)
+ {
+ _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft;
+ _Fcin.fcleft = 0;
+ }
+ *len = c;
+ if(c==1)
+ *s = state[*extra.next++];
+ else if(c==0)
+ _Fcin.fcleft = 0;
+ else
+ {
+ c = mbchar(extra.next);
+ *s = state['a'];
+ }
+ return(c);
+ }
+ switch(*len = mbsize(_Fcin.fcptr))
+ {
+ case -1:
+ if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX)
+ {
+ memcmp(extra.buff, _Fcin.fcptr, n);
+ _Fcin.fcptr = _Fcin.fclast;
+ for(i=n; i < MB_LEN_MAX+n; i++)
+ {
+ if((extra.buff[i] = fcgetc(c))==0)
+ break;
+ }
+ _Fcin.fcleft = n;
+ extra.next = extra.buff;
+ return(fcmbstate(state,s,len));
+ }
+ *len = 1;
+ /* fall through */
+ case 0:
+ case 1:
+ *s = state[c=fcget()];
+ break;
+ default:
+ c = mbchar(_Fcin.fcptr);
+ *s = state['a'];
+ }
+ return(c);
+}
+