summaryrefslogtreecommitdiff
path: root/src/lib/libast/sfio
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libast/sfio')
-rw-r--r--src/lib/libast/sfio/_sfclrerr.c34
-rw-r--r--src/lib/libast/sfio/_sfdlen.c34
-rw-r--r--src/lib/libast/sfio/_sfeof.c34
-rw-r--r--src/lib/libast/sfio/_sferror.c34
-rw-r--r--src/lib/libast/sfio/_sffileno.c34
-rw-r--r--src/lib/libast/sfio/_sfgetc.c34
-rw-r--r--src/lib/libast/sfio/_sfgetl.c42
-rw-r--r--src/lib/libast/sfio/_sfgetl2.c50
-rw-r--r--src/lib/libast/sfio/_sfgetu.c42
-rw-r--r--src/lib/libast/sfio/_sfgetu2.c50
-rw-r--r--src/lib/libast/sfio/_sfllen.c34
-rw-r--r--src/lib/libast/sfio/_sfopen.c219
-rw-r--r--src/lib/libast/sfio/_sfputc.c35
-rw-r--r--src/lib/libast/sfio/_sfputd.c96
-rw-r--r--src/lib/libast/sfio/_sfputl.c82
-rw-r--r--src/lib/libast/sfio/_sfputm.c78
-rw-r--r--src/lib/libast/sfio/_sfputu.c75
-rw-r--r--src/lib/libast/sfio/_sfslen.c33
-rw-r--r--src/lib/libast/sfio/_sfstacked.c34
-rw-r--r--src/lib/libast/sfio/_sfulen.c34
-rw-r--r--src/lib/libast/sfio/_sfvalue.c34
-rw-r--r--src/lib/libast/sfio/sfclose.c178
-rw-r--r--src/lib/libast/sfio/sfclrlock.c63
-rw-r--r--src/lib/libast/sfio/sfcvt.c532
-rw-r--r--src/lib/libast/sfio/sfdisc.c271
-rw-r--r--src/lib/libast/sfio/sfdlen.c58
-rw-r--r--src/lib/libast/sfio/sfecvt.c38
-rw-r--r--src/lib/libast/sfio/sfexcept.c133
-rw-r--r--src/lib/libast/sfio/sfextern.c99
-rw-r--r--src/lib/libast/sfio/sffcvt.c38
-rw-r--r--src/lib/libast/sfio/sffilbuf.c116
-rw-r--r--src/lib/libast/sfio/sfflsbuf.c126
-rw-r--r--src/lib/libast/sfio/sfgetd.c79
-rw-r--r--src/lib/libast/sfio/sfgetl.c70
-rw-r--r--src/lib/libast/sfio/sfgetm.c68
-rw-r--r--src/lib/libast/sfio/sfgetr.c169
-rw-r--r--src/lib/libast/sfio/sfgetu.c67
-rw-r--r--src/lib/libast/sfio/sfhdr.h1302
-rw-r--r--src/lib/libast/sfio/sfllen.c39
-rw-r--r--src/lib/libast/sfio/sfmode.c596
-rw-r--r--src/lib/libast/sfio/sfmove.c242
-rw-r--r--src/lib/libast/sfio/sfmutex.c69
-rw-r--r--src/lib/libast/sfio/sfnew.c129
-rw-r--r--src/lib/libast/sfio/sfnotify.c38
-rw-r--r--src/lib/libast/sfio/sfnputc.c81
-rw-r--r--src/lib/libast/sfio/sfopen.c40
-rw-r--r--src/lib/libast/sfio/sfpeek.c89
-rw-r--r--src/lib/libast/sfio/sfpkrd.c325
-rw-r--r--src/lib/libast/sfio/sfpoll.c250
-rw-r--r--src/lib/libast/sfio/sfpool.c369
-rw-r--r--src/lib/libast/sfio/sfpopen.c293
-rw-r--r--src/lib/libast/sfio/sfprintf.c114
-rw-r--r--src/lib/libast/sfio/sfprints.c125
-rw-r--r--src/lib/libast/sfio/sfpurge.c98
-rw-r--r--src/lib/libast/sfio/sfputd.c35
-rw-r--r--src/lib/libast/sfio/sfputl.c35
-rw-r--r--src/lib/libast/sfio/sfputm.c36
-rw-r--r--src/lib/libast/sfio/sfputr.c136
-rw-r--r--src/lib/libast/sfio/sfputu.c35
-rw-r--r--src/lib/libast/sfio/sfraise.c107
-rw-r--r--src/lib/libast/sfio/sfrd.c317
-rw-r--r--src/lib/libast/sfio/sfread.c140
-rw-r--r--src/lib/libast/sfio/sfreserve.c210
-rw-r--r--src/lib/libast/sfio/sfresize.c83
-rw-r--r--src/lib/libast/sfio/sfscanf.c102
-rw-r--r--src/lib/libast/sfio/sfseek.c281
-rw-r--r--src/lib/libast/sfio/sfset.c99
-rw-r--r--src/lib/libast/sfio/sfsetbuf.c426
-rw-r--r--src/lib/libast/sfio/sfsetfd.c136
-rw-r--r--src/lib/libast/sfio/sfsize.c109
-rw-r--r--src/lib/libast/sfio/sfsk.c106
-rw-r--r--src/lib/libast/sfio/sfstack.c115
-rw-r--r--src/lib/libast/sfio/sfstrtod.c157
-rw-r--r--src/lib/libast/sfio/sfstrtof.h568
-rw-r--r--src/lib/libast/sfio/sfswap.c119
-rw-r--r--src/lib/libast/sfio/sfsync.c172
-rw-r--r--src/lib/libast/sfio/sftable.c543
-rw-r--r--src/lib/libast/sfio/sftell.c59
-rw-r--r--src/lib/libast/sfio/sftmp.c402
-rw-r--r--src/lib/libast/sfio/sfungetc.c108
-rw-r--r--src/lib/libast/sfio/sfvprintf.c1445
-rw-r--r--src/lib/libast/sfio/sfvscanf.c1100
-rw-r--r--src/lib/libast/sfio/sfwalk.c67
-rw-r--r--src/lib/libast/sfio/sfwr.c252
-rw-r--r--src/lib/libast/sfio/sfwrite.c171
-rw-r--r--src/lib/libast/sfio/vthread.h219
86 files changed, 15336 insertions, 0 deletions
diff --git a/src/lib/libast/sfio/_sfclrerr.c b/src/lib/libast/sfio/_sfclrerr.c
new file mode 100644
index 0000000..e00dc1b
--- /dev/null
+++ b/src/lib/libast/sfio/_sfclrerr.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfclrerr
+
+#if __STD_C
+int sfclrerr(reg Sfio_t* f)
+#else
+int sfclrerr(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_clrerr(f);
+}
diff --git a/src/lib/libast/sfio/_sfdlen.c b/src/lib/libast/sfio/_sfdlen.c
new file mode 100644
index 0000000..0b0a9f5
--- /dev/null
+++ b/src/lib/libast/sfio/_sfdlen.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfdlen
+
+#if __STD_C
+int sfdlen(reg Sfdouble_t v)
+#else
+int sfdlen(v)
+reg Sfdouble_t v;
+#endif
+{
+ return __sf_dlen(v);
+}
diff --git a/src/lib/libast/sfio/_sfeof.c b/src/lib/libast/sfio/_sfeof.c
new file mode 100644
index 0000000..63dc002
--- /dev/null
+++ b/src/lib/libast/sfio/_sfeof.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfeof
+
+#if __STD_C
+int sfeof(reg Sfio_t* f)
+#else
+int sfeof(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_eof(f);
+}
diff --git a/src/lib/libast/sfio/_sferror.c b/src/lib/libast/sfio/_sferror.c
new file mode 100644
index 0000000..43b1a03
--- /dev/null
+++ b/src/lib/libast/sfio/_sferror.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sferror
+
+#if __STD_C
+int sferror(reg Sfio_t* f)
+#else
+int sferror(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_error(f);
+}
diff --git a/src/lib/libast/sfio/_sffileno.c b/src/lib/libast/sfio/_sffileno.c
new file mode 100644
index 0000000..f61a830
--- /dev/null
+++ b/src/lib/libast/sfio/_sffileno.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sffileno
+
+#if __STD_C
+int sffileno(reg Sfio_t* f)
+#else
+int sffileno(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_fileno(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetc.c b/src/lib/libast/sfio/_sfgetc.c
new file mode 100644
index 0000000..08a51b3
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetc.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfgetc
+
+#if __STD_C
+int sfgetc(reg Sfio_t* f)
+#else
+int sfgetc(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_getc(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetl.c b/src/lib/libast/sfio/_sfgetl.c
new file mode 100644
index 0000000..cc66462
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetl.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/*
+ * for backwards compatibility with pre-threaded sfgetl() inline
+ */
+
+#ifdef __EXPORT__
+#define extern __EXPORT__
+#endif
+
+extern
+#if __STD_C
+Sflong_t _sfgetl(reg Sfio_t* f)
+#else
+Sflong_t _sfgetl(f)
+reg Sfio_t* f;
+#endif
+{
+ sfungetc(f, (unsigned char)_SF_(f)->val);
+ return sfgetl(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetl2.c b/src/lib/libast/sfio/_sfgetl2.c
new file mode 100644
index 0000000..a6f9373
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetl2.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/* OBSOLETE 19961031 -- for shared library compatibility */
+
+#include "sfhdr.h"
+
+#undef _sfgetl2
+
+_BEGIN_EXTERNS_
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern long _sfgetl2 _ARG_((Sfio_t*, long));
+
+#undef extern
+_END_EXTERNS_
+
+#if __STD_C
+long _sfgetl2(reg Sfio_t* f, long v)
+#else
+long _sfgetl2(f, v)
+reg Sfio_t* f;
+long v;
+#endif
+{
+ if (v < 0)
+ return -1;
+ sfungetc(f, v);
+ return sfgetl(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetu.c b/src/lib/libast/sfio/_sfgetu.c
new file mode 100644
index 0000000..183f1a4
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetu.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/*
+ * for backwards compatibility with pre-threaded sfgetl() inline
+ */
+
+#ifdef __EXPORT__
+#define extern __EXPORT__
+#endif
+
+extern
+#if __STD_C
+Sfulong_t _sfgetu(reg Sfio_t* f)
+#else
+Sfulong_t _sfgetu(f)
+reg Sfio_t* f;
+#endif
+{
+ sfungetc(f, (unsigned char)_SF_(f)->val);
+ return sfgetu(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetu2.c b/src/lib/libast/sfio/_sfgetu2.c
new file mode 100644
index 0000000..27f5661
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetu2.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/* OBSOLETE 19961031 -- for shared library compatibility */
+
+#include "sfhdr.h"
+
+#undef _sfgetu2
+
+_BEGIN_EXTERNS_
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern long _sfgetu2 _ARG_((Sfio_t*, long));
+
+#undef extern
+_END_EXTERNS_
+
+#if __STD_C
+long _sfgetu2(reg Sfio_t* f, long v)
+#else
+long _sfgetu2(f, v)
+reg Sfio_t* f;
+long v;
+#endif
+{
+ if (v < 0)
+ return -1;
+ sfungetc(f, v);
+ return sfgetu(f);
+}
diff --git a/src/lib/libast/sfio/_sfllen.c b/src/lib/libast/sfio/_sfllen.c
new file mode 100644
index 0000000..2e735e3
--- /dev/null
+++ b/src/lib/libast/sfio/_sfllen.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfllen
+
+#if __STD_C
+int sfllen(reg Sflong_t v)
+#else
+int sfllen(v)
+reg Sflong_t v;
+#endif
+{
+ return __sf_llen(v);
+}
diff --git a/src/lib/libast/sfio/_sfopen.c b/src/lib/libast/sfio/_sfopen.c
new file mode 100644
index 0000000..9ad93fc
--- /dev/null
+++ b/src/lib/libast/sfio/_sfopen.c
@@ -0,0 +1,219 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Open a file/string for IO.
+** If f is not nil, it is taken as an existing stream that should be
+** closed and its structure reused for the new stream.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+extern
+#undef extern
+
+#if __STD_C
+Sfio_t* _sfopen(Sfio_t* f, const char* file, const char* mode)
+#else
+Sfio_t* _sfopen(f,file,mode)
+Sfio_t* f; /* old stream structure */
+char* file; /* file/string to be opened */
+char* mode; /* mode of the stream */
+#endif
+{
+ int fd, oldfd, oflags, sflags;
+ SFMTXDECL(f);
+
+ /* get the control flags */
+ if((sflags = _sftype(mode,&oflags,NIL(int*))) == 0)
+ return NIL(Sfio_t*);
+
+ /* changing the control flags */
+ if(f && !file && !((f->flags|sflags)&SF_STRING) )
+ { SFMTXENTER(f, NIL(Sfio_t*));
+
+ if(f->mode&SF_INIT ) /* stream uninitialized, ok to set flags */
+ { f->flags |= (sflags & (SF_FLAGS & ~SF_RDWR));
+
+ if((sflags &= SF_RDWR) != 0) /* reset read/write modes */
+ { f->flags = (f->flags & ~SF_RDWR) | sflags;
+
+ if((f->flags&SF_RDWR) == SF_RDWR)
+ f->bits |= SF_BOTH;
+ else f->bits &= ~SF_BOTH;
+
+ if(f->flags&SF_READ)
+ f->mode = (f->mode&~SF_WRITE)|SF_READ;
+ else f->mode = (f->mode&~SF_READ)|SF_WRITE;
+ }
+ }
+ else /* make sure there is no buffered data */
+ { if(sfsync(f) < 0)
+ SFMTXRETURN(f,NIL(Sfio_t*));
+ }
+
+ if(f->file >= 0 && (oflags &= (O_TEXT|O_BINARY|O_APPEND)) != 0 )
+ { /* set file access control */
+ int ctl = sysfcntlf(f->file, F_GETFL, 0);
+ ctl = (ctl & ~(O_TEXT|O_BINARY|O_APPEND)) | oflags;
+ sysfcntlf(f->file, F_SETFL, ctl);
+ }
+
+ SFMTXRETURN(f,f);
+ }
+
+ if(sflags&SF_STRING)
+ { f = sfnew(f,(char*)file,
+ file ? (size_t)strlen((char*)file) : (size_t)SF_UNBOUND,
+ -1,sflags);
+ }
+ else
+ { if(!file)
+ return NIL(Sfio_t*);
+
+#if _has_oflags /* open the file */
+ while((fd = sysopenf((char*)file,oflags,SF_CREATMODE)) < 0 && errno == EINTR)
+ errno = 0;
+#else
+ while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 && errno == EINTR)
+ errno = 0;
+ if(fd >= 0)
+ { if((oflags&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
+ { CLOSE(fd); /* error: file already exists */
+ return NIL(Sfio_t*);
+ }
+ if(oflags&O_TRUNC ) /* truncate file */
+ { reg int tf;
+ while((tf = syscreatf(file,SF_CREATMODE)) < 0 &&
+ errno == EINTR)
+ errno = 0;
+ CLOSE(tf);
+ }
+ }
+ else if(oflags&O_CREAT)
+ { while((fd = syscreatf(file,SF_CREATMODE)) < 0 && errno == EINTR)
+ errno = 0;
+ if((oflags&O_ACCMODE) != O_WRONLY)
+ { /* the file now exists, reopen it for read/write */
+ CLOSE(fd);
+ while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 &&
+ errno == EINTR)
+ errno = 0;
+ }
+ }
+#endif
+ if(fd < 0)
+ return NIL(Sfio_t*);
+
+ /* we may have to reset the file descriptor to its old value */
+ oldfd = f ? f->file : -1;
+ if((f = sfnew(f,NIL(char*),(size_t)SF_UNBOUND,fd,sflags)) && oldfd >= 0)
+ (void)sfsetfd(f,oldfd);
+ }
+
+ return f;
+}
+
+#if __STD_C
+int _sftype(reg const char* mode, int* oflagsp, int* uflagp)
+#else
+int _sftype(mode, oflagsp, uflagp)
+reg char* mode;
+int* oflagsp;
+int* uflagp;
+#endif
+{
+ reg int sflags, oflags, uflag;
+
+ if(!mode)
+ return 0;
+
+ /* construct the open flags */
+ sflags = oflags = uflag = 0;
+ while(1) switch(*mode++)
+ {
+ case 'a' :
+ sflags |= SF_WRITE | SF_APPENDWR;
+ oflags |= O_WRONLY | O_APPEND | O_CREAT;
+ continue;
+ case 'b' :
+ oflags |= O_BINARY;
+ continue;
+ case 'm' :
+ sflags |= SF_MTSAFE;
+ uflag = 0;
+ continue;
+ case 'r' :
+ sflags |= SF_READ;
+ oflags |= O_RDONLY;
+ continue;
+ case 's' :
+ sflags |= SF_STRING;
+ continue;
+ case 't' :
+ oflags |= O_TEXT;
+ continue;
+ case 'u' :
+ sflags &= ~SF_MTSAFE;
+ uflag = 1;
+ continue;
+ case 'w' :
+ sflags |= SF_WRITE;
+ oflags |= O_WRONLY | O_CREAT;
+ if(!(sflags&SF_READ))
+ oflags |= O_TRUNC;
+ continue;
+ case 'x' :
+ oflags |= O_EXCL;
+ continue;
+ case 'F':
+ /* stdio compatibility -- fd >= FOPEN_MAX (or other magic number) ok */
+ continue;
+ case 'W' :
+ sflags |= SF_WCWIDTH;
+ uflag = 0;
+ continue;
+ case '+' :
+ if(sflags)
+ sflags |= SF_READ|SF_WRITE;
+ continue;
+ default :
+ if(!(oflags&O_CREAT) )
+ oflags &= ~O_EXCL;
+#if _WIN32 && !_WINIX
+ if(!(oflags&(O_BINARY|O_TEXT)))
+ oflags |= O_BINARY;
+#endif
+ if((sflags&SF_RDWR) == SF_RDWR)
+ oflags = (oflags&~O_ACCMODE)|O_RDWR;
+ if(oflagsp)
+ *oflagsp = oflags;
+ if(uflagp)
+ *uflagp = uflag;
+ if((sflags&(SF_STRING|SF_RDWR)) == SF_STRING)
+ sflags |= SF_READ;
+ return sflags;
+ }
+}
diff --git a/src/lib/libast/sfio/_sfputc.c b/src/lib/libast/sfio/_sfputc.c
new file mode 100644
index 0000000..8f577e4
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputc.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputc
+
+#if __STD_C
+int sfputc(reg Sfio_t* f, reg int c)
+#else
+int sfputc(f,c)
+reg Sfio_t* f;
+reg int c;
+#endif
+{
+ return __sf_putc(f,c);
+}
diff --git a/src/lib/libast/sfio/_sfputd.c b/src/lib/libast/sfio/_sfputd.c
new file mode 100644
index 0000000..733caa6
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputd.c
@@ -0,0 +1,96 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out a floating point value in a portable format
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputd(Sfio_t* f, Sfdouble_t v)
+#else
+int _sfputd(f,v)
+Sfio_t* f;
+Sfdouble_t v;
+#endif
+{
+#define N_ARRAY (16*sizeof(Sfdouble_t))
+ reg ssize_t n, w;
+ reg uchar *s, *ends;
+ int exp;
+ uchar c[N_ARRAY];
+ Sfdouble_t x;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* get the sign of v */
+ if(v < 0.)
+ { v = -v;
+ n = 1;
+ }
+ else n = 0;
+
+ /* make the magnitude of v < 1 */
+ if(v != 0.)
+ v = frexpl(v,&exp);
+ else exp = 0;
+
+ /* code the sign of v and exp */
+ if((w = exp) < 0)
+ { n |= 02;
+ w = -w;
+ }
+
+ /* write out the signs and the exp */
+ SFOPEN(f,0);
+ if(sfputc(f,n) < 0 || (w = sfputu(f,w)) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+ w += 1;
+
+ s = (ends = &c[0])+sizeof(c);
+ while(s > ends)
+ { /* get 2^SF_PRECIS precision at a time */
+ n = (int)(x = ldexpl(v,SF_PRECIS));
+ *--s = n|SF_MORE;
+ v = x-n;
+ if(v <= 0.)
+ break;
+ }
+
+ /* last byte is not SF_MORE */
+ ends = &c[0] + sizeof(c) -1;
+ *ends &= ~SF_MORE;
+
+ /* write out coded bytes */
+ n = ends - s + 1;
+ w = SFWRITE(f,(Void_t*)s,n) == n ? w+n : -1;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f,w);
+}
diff --git a/src/lib/libast/sfio/_sfputl.c b/src/lib/libast/sfio/_sfputl.c
new file mode 100644
index 0000000..df3d9a7
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputl.c
@@ -0,0 +1,82 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out a long value in a portable format
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputl(Sfio_t* f, Sflong_t v)
+#else
+int _sfputl(f,v)
+Sfio_t* f; /* write a portable long to this stream */
+Sflong_t v; /* the value to be written */
+#endif
+{
+#define N_ARRAY (2*sizeof(Sflong_t))
+ reg uchar *s, *ps;
+ reg ssize_t n, p;
+ uchar c[N_ARRAY];
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ s = ps = &(c[N_ARRAY-1]);
+ if(v < 0)
+ { /* add 1 to avoid 2-complement problems with -SF_MAXINT */
+ v = -(v+1);
+ *s = (uchar)(SFSVALUE(v) | SF_SIGN);
+ }
+ else *s = (uchar)(SFSVALUE(v));
+ v = (Sfulong_t)v >> SF_SBITS;
+
+ while(v > 0)
+ { *--s = (uchar)(SFUVALUE(v) | SF_MORE);
+ v = (Sfulong_t)v >> SF_UBITS;
+ }
+ n = (ps-s)+1;
+
+ if(n > 8 || SFWPEEK(f,ps,p) < n)
+ n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */
+ else
+ { switch(n)
+ {
+ case 8 : *ps++ = *s++;
+ case 7 : *ps++ = *s++;
+ case 6 : *ps++ = *s++;
+ case 5 : *ps++ = *s++;
+ case 4 : *ps++ = *s++;
+ case 3 : *ps++ = *s++;
+ case 2 : *ps++ = *s++;
+ case 1 : *ps++ = *s++;
+ }
+ f->next = ps;
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, n);
+}
diff --git a/src/lib/libast/sfio/_sfputm.c b/src/lib/libast/sfio/_sfputm.c
new file mode 100644
index 0000000..1fa9d9d
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputm.c
@@ -0,0 +1,78 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out an unsigned long value in a portable format.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t m)
+#else
+int _sfputm(f,v,m)
+Sfio_t* f; /* write a portable ulong to this stream */
+Sfulong_t v; /* the unsigned value to be written */
+Sfulong_t m; /* the max value of the range */
+#endif
+{
+#define N_ARRAY (2*sizeof(Sfulong_t))
+ reg uchar *s, *ps;
+ reg ssize_t n, p;
+ uchar c[N_ARRAY];
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(v > m || (f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) )
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* code v as integers in base SF_UBASE */
+ s = ps = &(c[N_ARRAY-1]);
+ *s = (uchar)SFBVALUE(v);
+ while((m >>= SF_BBITS) > 0 )
+ { v >>= SF_BBITS;
+ *--s = (uchar)SFBVALUE(v);
+ }
+ n = (ps-s)+1;
+
+ if(n > 8 || SFWPEEK(f,ps,p) < n)
+ n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */
+ else
+ { switch(n)
+ {
+ case 8 : *ps++ = *s++;
+ case 7 : *ps++ = *s++;
+ case 6 : *ps++ = *s++;
+ case 5 : *ps++ = *s++;
+ case 4 : *ps++ = *s++;
+ case 3 : *ps++ = *s++;
+ case 2 : *ps++ = *s++;
+ case 1 : *ps++ = *s++;
+ }
+ f->next = ps;
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, (int)n);
+}
diff --git a/src/lib/libast/sfio/_sfputu.c b/src/lib/libast/sfio/_sfputu.c
new file mode 100644
index 0000000..e632d9d
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputu.c
@@ -0,0 +1,75 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out an unsigned long value in a portable format.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputu(Sfio_t* f, Sfulong_t v)
+#else
+int _sfputu(f,v)
+Sfio_t* f; /* write a portable ulong to this stream */
+Sfulong_t v; /* the unsigned value to be written */
+#endif
+{
+#define N_ARRAY (2*sizeof(Sfulong_t))
+ reg uchar *s, *ps;
+ reg ssize_t n, p;
+ uchar c[N_ARRAY];
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* code v as integers in base SF_UBASE */
+ s = ps = &(c[N_ARRAY-1]);
+ *s = (uchar)SFUVALUE(v);
+ while((v >>= SF_UBITS) )
+ *--s = (uchar)(SFUVALUE(v) | SF_MORE);
+ n = (ps-s)+1;
+
+ if(n > 8 || SFWPEEK(f,ps,p) < n)
+ n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */
+ else
+ { switch(n)
+ {
+ case 8 : *ps++ = *s++;
+ case 7 : *ps++ = *s++;
+ case 6 : *ps++ = *s++;
+ case 5 : *ps++ = *s++;
+ case 4 : *ps++ = *s++;
+ case 3 : *ps++ = *s++;
+ case 2 : *ps++ = *s++;
+ case 1 : *ps++ = *s++;
+ }
+ f->next = ps;
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, (int)n);
+}
diff --git a/src/lib/libast/sfio/_sfslen.c b/src/lib/libast/sfio/_sfslen.c
new file mode 100644
index 0000000..e34958e
--- /dev/null
+++ b/src/lib/libast/sfio/_sfslen.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfslen
+
+#if __STD_C
+ssize_t sfslen(void)
+#else
+ssize_t sfslen()
+#endif
+{
+ return __sf_slen();
+}
diff --git a/src/lib/libast/sfio/_sfstacked.c b/src/lib/libast/sfio/_sfstacked.c
new file mode 100644
index 0000000..a785ed5
--- /dev/null
+++ b/src/lib/libast/sfio/_sfstacked.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfstacked
+
+#if __STD_C
+int sfstacked(reg Sfio_t* f)
+#else
+int sfstacked(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_stacked(f);
+}
diff --git a/src/lib/libast/sfio/_sfulen.c b/src/lib/libast/sfio/_sfulen.c
new file mode 100644
index 0000000..71bb258
--- /dev/null
+++ b/src/lib/libast/sfio/_sfulen.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfulen
+
+#if __STD_C
+int sfulen(reg Sfulong_t v)
+#else
+int sfulen(v)
+reg Sfulong_t v;
+#endif
+{
+ return __sf_ulen(v);
+}
diff --git a/src/lib/libast/sfio/_sfvalue.c b/src/lib/libast/sfio/_sfvalue.c
new file mode 100644
index 0000000..b8dcce7
--- /dev/null
+++ b/src/lib/libast/sfio/_sfvalue.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfvalue
+
+#if __STD_C
+ssize_t sfvalue(reg Sfio_t* f)
+#else
+ssize_t sfvalue(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_value(f);
+}
diff --git a/src/lib/libast/sfio/sfclose.c b/src/lib/libast/sfio/sfclose.c
new file mode 100644
index 0000000..4fb6529
--- /dev/null
+++ b/src/lib/libast/sfio/sfclose.c
@@ -0,0 +1,178 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Close a stream. A file stream is synced before closing.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int sfclose(Sfio_t* f)
+#else
+int sfclose(f)
+Sfio_t* f;
+#endif
+{
+ reg int local, ex, rv;
+ Void_t* data = NIL(Void_t*);
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, -1);
+
+ GETLOCAL(f,local);
+
+ if(!(f->mode&SF_INIT) &&
+ SFMODE(f,local) != (f->mode&SF_RDWR) &&
+ SFMODE(f,local) != (f->mode&(SF_READ|SF_SYNCED)) &&
+ _sfmode(f,SF_SYNCED,local) < 0)
+ SFMTXRETURN(f,-1);
+
+ /* closing a stack of streams */
+ while(f->push)
+ { reg Sfio_t* pop;
+
+ if(!(pop = (*_Sfstack)(f,NIL(Sfio_t*))) )
+ SFMTXRETURN(f,-1);
+
+ if(sfclose(pop) < 0)
+ { (*_Sfstack)(f,pop);
+ SFMTXRETURN(f,-1);
+ }
+ }
+
+ rv = 0;
+ if(f->disc == _Sfudisc) /* closing the ungetc stream */
+ f->disc = NIL(Sfdisc_t*);
+ else if(f->file >= 0) /* sync file pointer */
+ { f->bits |= SF_ENDING;
+ rv = sfsync(f);
+ }
+
+ SFLOCK(f,0);
+
+ /* raise discipline exceptions */
+ if(f->disc && (ex = SFRAISE(f,local ? SF_NEW : SF_CLOSING,NIL(Void_t*))) != 0)
+ SFMTXRETURN(f,ex);
+
+ if(!local && f->pool)
+ { /* remove from pool */
+ if(f->pool == &_Sfpool)
+ { reg int n;
+
+ POOLMTXLOCK(&_Sfpool);
+ for(n = 0; n < _Sfpool.n_sf; ++n)
+ { if(_Sfpool.sf[n] != f)
+ continue;
+ /* found it */
+ _Sfpool.n_sf -= 1;
+ for(; n < _Sfpool.n_sf; ++n)
+ _Sfpool.sf[n] = _Sfpool.sf[n+1];
+ break;
+ }
+ POOLMTXUNLOCK(&_Sfpool);
+ }
+ else
+ { f->mode &= ~SF_LOCK; /**/ASSERT(_Sfpmove);
+ if((*_Sfpmove)(f,-1) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f,-1);
+ }
+ f->mode |= SF_LOCK;
+ }
+ f->pool = NIL(Sfpool_t*);
+ }
+
+ if(f->data && (!local || (f->flags&SF_STRING) || (f->bits&SF_MMAP) ) )
+ { /* free buffer */
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ SFMUNMAP(f,f->data,f->endb-f->data);
+ else
+#endif
+ if(f->flags&SF_MALLOC)
+ data = (Void_t*)f->data;
+
+ f->data = NIL(uchar*);
+ f->size = -1;
+ }
+
+ /* zap the file descriptor */
+ if(_Sfnotify)
+ (*_Sfnotify)(f, SF_CLOSING, (void*)((long)f->file));
+ if(f->file >= 0 && !(f->flags&SF_STRING))
+ { while(sysclosef(f->file) < 0 )
+ { if(errno == EINTR)
+ errno = 0;
+ else
+ { rv = -1;
+ break;
+ }
+ }
+ }
+ f->file = -1;
+
+ SFKILL(f);
+ f->flags &= SF_STATIC;
+ f->here = 0;
+ f->extent = -1;
+ f->endb = f->endr = f->endw = f->next = f->data;
+
+ /* zap any associated auxiliary buffer */
+ if(f->rsrv)
+ { free(f->rsrv);
+ f->rsrv = NIL(Sfrsrv_t*);
+ }
+
+ /* delete any associated sfpopen-data */
+ if(f->proc && _sfpclose(f) < 0 )
+ rv = -1;
+
+ /* destroy the mutex */
+ if(f->mutex)
+ { (void)vtmtxclrlock(f->mutex);
+ if(f != sfstdin && f != sfstdout && f != sfstderr)
+ { (void)vtmtxclose(f->mutex);
+ f->mutex = NIL(Vtmutex_t*);
+ }
+ }
+
+ if(!local)
+ { if(f->disc && (ex = SFRAISE(f,SF_FINAL,NIL(Void_t*))) != 0 )
+ { rv = ex;
+ goto done;
+ }
+
+ if(!(f->flags&SF_STATIC) )
+ free(f);
+ else
+ { f->disc = NIL(Sfdisc_t*);
+ f->stdio = NIL(Void_t*);
+ f->mode = SF_AVAIL;
+ }
+ }
+
+done:
+ if(data)
+ free(data);
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfclrlock.c b/src/lib/libast/sfio/sfclrlock.c
new file mode 100644
index 0000000..711756a
--- /dev/null
+++ b/src/lib/libast/sfio/sfclrlock.c
@@ -0,0 +1,63 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Function to clear a locked stream.
+** This is useful for programs that longjmp from the mid of an sfio function.
+** There is no guarantee on data integrity in such a case.
+**
+** Written by Kiem-Phong Vo
+*/
+#if __STD_C
+int sfclrlock(Sfio_t* f)
+#else
+int sfclrlock(f)
+Sfio_t *f;
+#endif
+{
+ int rv;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ /* already closed */
+ if(f && (f->mode&SF_AVAIL))
+ return 0;
+
+ SFMTXENTER(f,0);
+
+ /* clear error bits */
+ f->flags &= ~(SF_ERROR|SF_EOF);
+
+ /* clear peek locks */
+ if(f->mode&SF_PKRD)
+ { f->here -= f->endb-f->next;
+ f->endb = f->next;
+ }
+
+ SFCLRBITS(f);
+
+ /* throw away all lock bits except for stacking state SF_PUSH */
+ f->mode &= (SF_RDWR|SF_INIT|SF_POOL|SF_PUSH|SF_SYNCED|SF_STDIO);
+
+ rv = (f->mode&SF_PUSH) ? 0 : (f->flags&SF_FLAGS);
+
+ SFMTXRETURN(f, rv);
+}
diff --git a/src/lib/libast/sfio/sfcvt.c b/src/lib/libast/sfio/sfcvt.c
new file mode 100644
index 0000000..ca01f20
--- /dev/null
+++ b/src/lib/libast/sfio/sfcvt.c
@@ -0,0 +1,532 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if __STDC__
+#include "FEATURE/isoc99"
+#endif
+#include "sfhdr.h"
+
+/* Convert a floating point value to ASCII.
+**
+** Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT)
+*/
+
+static char *lc_inf = "inf", *uc_inf = "INF";
+static char *lc_nan = "nan", *uc_nan = "NAN";
+static char *Zero = "0";
+#define SF_INF ((_Sfi = 3), strlcpy(buf, (format & SFFMT_UPPER) ? uc_inf : lc_inf, size), buf)
+#define SF_NAN ((_Sfi = 3), strlcpy(buf, (format & SFFMT_UPPER) ? uc_nan : lc_nan, size), buf)
+#define SF_ZERO ((_Sfi = 1), strlcpy(buf, Zero, size), buf)
+#define SF_INTPART (SF_IDIGITS/2)
+
+#if ! _lib_isnan
+#if _lib_fpclassify
+#define isnan(n) (fpclassify(n)==FP_NAN)
+#define isnanl(n) (fpclassify(n)==FP_NAN)
+#else
+#define isnan(n) (memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0)
+#define isnanl(n) (memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0)
+#endif
+#else
+#if ! _lib_isnanl
+#define isnanl(n) isnan(n)
+#endif
+#endif
+
+#if ! _lib_signbit && defined(signbit)
+#undef _lib_signbit
+#define _lib_signbit 1
+#endif
+
+#if ! _lib_signbit
+#if ! _ast_fltmax_double
+static int neg0ld(Sfdouble_t f)
+{
+ Sfdouble_t z = -0.0;
+ return !memcmp(&f, &z, sizeof(f));
+}
+#endif
+static int neg0d(double f)
+{
+ double z = -0.0;
+ return !memcmp(&f, &z, sizeof(f));
+}
+#endif
+
+#if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
+#define CVT_LDBL_INT long
+#define CVT_LDBL_MAXINT LONG_MAX
+#else
+#if UINT_DIG && UINT_DIG < (DBL_DIG-1)
+#define CVT_LDBL_INT int
+#define CVT_LDBL_MAXINT INT_MAX
+#else
+#define CVT_LDBL_INT long
+#define CVT_LDBL_MAXINT SF_MAXLONG
+#endif
+#endif
+
+#if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
+#define CVT_DBL_INT long
+#define CVT_DBL_MAXINT LONG_MAX
+#else
+#if UINT_DIG && UINT_DIG < (DBL_DIG-1)
+#define CVT_DBL_INT int
+#define CVT_DBL_MAXINT INT_MAX
+#else
+#define CVT_DBL_INT long
+#define CVT_DBL_MAXINT SF_MAXLONG
+#endif
+#endif
+
+#if __STD_C
+char* _sfcvt(Void_t* vp, char* buf, size_t size, int n_digit,
+ int* decpt, int* sign, int* len, int format)
+#else
+char* _sfcvt(vp,buf,size,n_digit,decpt,sign,len,format)
+Void_t* vp; /* pointer to value to convert */
+char* buf; /* conversion goes here */
+size_t size; /* size of buf */
+int n_digit; /* number of digits wanted */
+int* decpt; /* to return decimal point */
+int* sign; /* to return sign */
+int* len; /* return string length */
+int format; /* conversion format */
+#endif
+{
+ reg char *sp;
+ reg long n, v;
+ reg char *ep, *b, *endsp, *t;
+ int x;
+ _ast_flt_unsigned_max_t m;
+
+ static char lx[] = "0123456789abcdef";
+ static char ux[] = "0123456789ABCDEF";
+
+ *sign = *decpt = 0;
+
+#if !_ast_fltmax_double
+ if(format&SFFMT_LDOUBLE)
+ { Sfdouble_t f = *(Sfdouble_t*)vp;
+
+ if(isnanl(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (f < 0)
+#endif
+ *sign = 1;
+ return SF_NAN;
+ }
+#if _lib_isinf
+ if (n = isinf(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (n < 0 || f < 0)
+#endif
+ *sign = 1;
+ return SF_INF;
+ }
+#endif
+# if _c99_in_the_wild
+# if _lib_signbit
+ if (signbit(f))
+# else
+# if _lib_copysignl
+ if (copysignl(1.0, f) < 0.0)
+# else
+# if _lib_copysign
+ if (copysign(1.0, (double)f) < 0.0)
+# else
+ if (f < 0.0)
+# endif
+# endif
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+# if _lib_fpclassify
+ switch (fpclassify(f))
+ {
+ case FP_INFINITE:
+ return SF_INF;
+ case FP_NAN:
+ return SF_NAN;
+ case FP_ZERO:
+ return SF_ZERO;
+ }
+# endif
+# else
+# if _lib_signbit
+ if (signbit(f))
+# else
+ if (f < 0.0 || f == 0.0 && neg0ld(f))
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+# endif
+ if(f < LDBL_MIN)
+ return SF_ZERO;
+ if(f > LDBL_MAX)
+ return SF_INF;
+
+ if(format & SFFMT_AFORMAT)
+ { Sfdouble_t g;
+ b = sp = buf;
+ ep = (format & SFFMT_UPPER) ? ux : lx;
+ if(n_digit <= 0 || n_digit >= (size - 9))
+ n_digit = size - 9;
+ endsp = sp + n_digit + 1;
+
+ g = frexpl(f, &x);
+ *decpt = x;
+ f = ldexpl(g, 8 * sizeof(m) - 3);
+
+ for (;;)
+ { m = f;
+ x = 8 * sizeof(m);
+ while ((x -= 4) >= 0)
+ { *sp++ = ep[(m >> x) & 0xf];
+ if (sp >= endsp)
+ goto around;
+ }
+ f -= m;
+ f = ldexpl(f, 8 * sizeof(m));
+ }
+ }
+
+ n = 0;
+ if(f >= (Sfdouble_t)CVT_LDBL_MAXINT)
+ { /* scale to a small enough number to fit an int */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f < _Sfpos10[v])
+ v -= 1;
+ else
+ {
+ f *= _Sfneg10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ } while(f >= (Sfdouble_t)CVT_LDBL_MAXINT);
+ }
+ else if(f > 0.0 && f < 0.1)
+ { /* scale to avoid excessive multiply by 10 below */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f <= _Sfneg10[v])
+ { f *= _Sfpos10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ else if (--v < 0)
+ break;
+ } while(f < 0.1);
+ n = -n;
+ }
+ *decpt = (int)n;
+
+ b = sp = buf + SF_INTPART;
+ if((v = (CVT_LDBL_INT)f) != 0)
+ { /* translate the integer part */
+ f -= (Sfdouble_t)v;
+
+ sfucvt(v,sp,n,ep,CVT_LDBL_INT,unsigned CVT_LDBL_INT);
+
+ n = b-sp;
+ if((*decpt += (int)n) >= SF_IDIGITS)
+ return SF_INF;
+ b = sp;
+ sp = buf + SF_INTPART;
+ }
+ else n = 0;
+
+ /* remaining number of digits to compute; add 1 for later rounding */
+ n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
+ if(n_digit > 0)
+ { if(n_digit > LDBL_DIG)
+ n_digit = LDBL_DIG;
+ n += n_digit;
+ }
+
+ if((ep = (sp+n)) > (endsp = buf+(size-2)))
+ ep = endsp;
+ if(sp > ep)
+ sp = ep;
+ else
+ {
+ if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
+ { Sfdouble_t d;
+ while((long)(d = f*10.) == 0)
+ { f = d;
+ *decpt -= 1;
+ }
+ }
+
+ while(sp < ep)
+ { /* generate fractional digits */
+ if(f <= 0.)
+ { /* fill with 0's */
+ do { *sp++ = '0'; } while(sp < ep);
+ goto done;
+ }
+ else if((n = (long)(f *= 10.)) < 10)
+ { *sp++ = '0' + n;
+ f -= n;
+ }
+ else /* n == 10 */
+ { do { *sp++ = '9'; } while(sp < ep);
+ }
+ }
+ }
+ } else
+#endif
+ { double f = *(double*)vp;
+
+ if(isnan(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (f < 0)
+#endif
+ *sign = 1;
+ return SF_NAN;
+ }
+#if _lib_isinf
+ if (n = isinf(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (n < 0 || f < 0)
+#endif
+ *sign = 1;
+ return SF_INF;
+ }
+#endif
+#if _c99_in_the_wild
+# if _lib_signbit
+ if (signbit(f))
+# else
+# if _lib_copysign
+ if (copysign(1.0, f) < 0.0)
+# else
+ if (f < 0.0)
+# endif
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+# if _lib_fpclassify
+ switch (fpclassify(f))
+ {
+ case FP_INFINITE:
+ return SF_INF;
+ case FP_NAN:
+ return SF_NAN;
+ case FP_ZERO:
+ return SF_ZERO;
+ }
+# endif
+#else
+# if _lib_signbit
+ if (signbit(f))
+# else
+ if (f < 0.0 || f == 0.0 && neg0d(f))
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+#endif
+ if(f < DBL_MIN)
+ return SF_ZERO;
+ if(f > DBL_MAX)
+ return SF_INF;
+
+ if(format & SFFMT_AFORMAT)
+ { double g;
+ b = sp = buf;
+ ep = (format & SFFMT_UPPER) ? ux : lx;
+ if(n_digit <= 0 || n_digit >= (size - 9))
+ n_digit = size - 9;
+ endsp = sp + n_digit + 1;
+
+ g = frexp(f, &x);
+ *decpt = x;
+ f = ldexp(g, 8 * sizeof(m) - 3);
+
+ for (;;)
+ { m = f;
+ x = 8 * sizeof(m);
+ while ((x -= 4) >= 0)
+ { *sp++ = ep[(m >> x) & 0xf];
+ if (sp >= endsp)
+ goto around;
+ }
+ f -= m;
+ f = ldexp(f, 8 * sizeof(m));
+ }
+ }
+ n = 0;
+ if(f >= (double)CVT_DBL_MAXINT)
+ { /* scale to a small enough number to fit an int */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f < _Sfpos10[v])
+ v -= 1;
+ else
+ { f *= _Sfneg10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ } while(f >= (double)CVT_DBL_MAXINT);
+ }
+ else if(f > 0.0 && f < 1e-8)
+ { /* scale to avoid excessive multiply by 10 below */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f <= _Sfneg10[v])
+ { f *= _Sfpos10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ else if(--v < 0)
+ break;
+ } while(f < 0.1);
+ n = -n;
+ }
+ *decpt = (int)n;
+
+ b = sp = buf + SF_INTPART;
+ if((v = (CVT_DBL_INT)f) != 0)
+ { /* translate the integer part */
+ f -= (double)v;
+
+ sfucvt(v,sp,n,ep,CVT_DBL_INT,unsigned CVT_DBL_INT);
+
+ n = b-sp;
+ if((*decpt += (int)n) >= SF_IDIGITS)
+ return SF_INF;
+ b = sp;
+ sp = buf + SF_INTPART;
+ }
+ else n = 0;
+
+ /* remaining number of digits to compute; add 1 for later rounding */
+ n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
+ if(n_digit > 0)
+ { if(n_digit > DBL_DIG)
+ n_digit = DBL_DIG;
+ n += n_digit;
+ }
+
+ if((ep = (sp+n)) > (endsp = buf+(size-2)))
+ ep = endsp;
+ if(sp > ep)
+ sp = ep;
+ else
+ {
+ if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
+ { reg double d;
+ while((long)(d = f*10.) == 0)
+ { f = d;
+ *decpt -= 1;
+ }
+ }
+
+ while(sp < ep)
+ { /* generate fractional digits */
+ if(f <= 0.)
+ { /* fill with 0's */
+ do { *sp++ = '0'; } while(sp < ep);
+ goto done;
+ }
+ else if((n = (long)(f *= 10.)) < 10)
+ { *sp++ = (char)('0' + n);
+ f -= n;
+ }
+ else /* n == 10 */
+ { do { *sp++ = '9'; } while(sp < ep);
+ break;
+ }
+ }
+ }
+ }
+
+ if(ep <= b)
+ ep = b+1;
+ else if(ep < endsp)
+ { /* round the last digit */
+ *--sp += 5;
+ while(*sp > '9')
+ { *sp = '0';
+ if(sp > b)
+ *--sp += 1;
+ else
+ { /* next power of 10 */
+ *sp = '1';
+ *decpt += 1;
+ if(!(format&SFFMT_EFORMAT))
+ { /* add one more 0 for %f precision */
+ ep[-1] = '0';
+ ep += 1;
+ }
+ }
+ }
+ }
+
+ done:
+ *--ep = '\0';
+ if(len)
+ *len = ep-b;
+ return b;
+ around:
+ if (((m >> x) & 0xf) >= 8)
+ { t = sp - 1;
+ for (;;)
+ { if (--t <= b)
+ { (*decpt)++;
+ break;
+ }
+ switch (*t)
+ {
+ case 'f':
+ case 'F':
+ *t = '0';
+ continue;
+ case '9':
+ *t = ep[10];
+ break;
+ default:
+ (*t)++;
+ break;
+ }
+ break;
+ }
+ }
+ ep = sp + 1;
+ goto done;
+}
diff --git a/src/lib/libast/sfio/sfdisc.c b/src/lib/libast/sfio/sfdisc.c
new file mode 100644
index 0000000..8ffc559
--- /dev/null
+++ b/src/lib/libast/sfio/sfdisc.c
@@ -0,0 +1,271 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Add a new discipline to the discipline stack. Each discipline
+** provides alternative I/O functions that are analogues of the
+** system calls.
+**
+** When the application fills or flushes the stream buffer, data
+** will be processed through discipline functions. A case deserving
+** consideration is stacking a discipline onto a read stream. Each
+** discipline operation implies buffer synchronization so the stream
+** buffer should be empty. However, a read stream representing an
+** unseekable device (eg, a pipe) may not be synchronizable. In that
+** case, any buffered data must then be fed to the new discipline
+** to preserve data processing semantics. This is done by creating
+** a temporary discipline to cache such buffered data and feed
+** them to the new discipline when its readf() asks for new data.
+** Care must then be taken to remove this temporary discipline
+** when it runs out of cached data.
+**
+** Written by Kiem-Phong Vo
+*/
+
+typedef struct _dccache_s
+{ Sfdisc_t disc;
+ uchar* data;
+ uchar* endb;
+} Dccache_t;
+
+#if __STD_C
+static int _dccaexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _dccaexcept(f,type,val,disc)
+Sfio_t* f;
+int type;
+Void_t* val;
+Sfdisc_t* disc;
+#endif
+{
+ if(disc && type == SF_FINAL)
+ free(disc);
+ return 0;
+}
+
+#if __STD_C
+static ssize_t _dccaread(Sfio_t* f, Void_t* buf, size_t size, Sfdisc_t* disc)
+#else
+static ssize_t _dccaread(f, buf, size, disc)
+Sfio_t* f;
+Void_t* buf;
+size_t size;
+Sfdisc_t* disc;
+#endif
+{
+ ssize_t sz;
+ Sfdisc_t *prev;
+ Dccache_t *dcca;
+
+ if(!f) /* bad stream */
+ return -1;
+
+ /* make sure that this is on the discipline stack */
+ for(prev = f->disc; prev; prev = prev->disc)
+ if(prev->disc == disc)
+ break;
+ if(!prev)
+ return -1;
+
+ if(size <= 0) /* nothing to do */
+ return size;
+
+ /* read from available data */
+ dcca = (Dccache_t*)disc;
+ if((sz = dcca->endb - dcca->data) > (ssize_t)size)
+ sz = (ssize_t)size;
+ memcpy(buf, dcca->data, sz);
+
+ if((dcca->data += sz) >= dcca->endb) /* free empty cache */
+ { prev->disc = disc->disc;
+ free(disc);
+ }
+
+ return sz;
+}
+
+#if __STD_C
+Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc)
+#else
+Sfdisc_t* sfdisc(f,disc)
+Sfio_t* f;
+Sfdisc_t* disc;
+#endif
+{
+ Sfdisc_t *d, *rdisc;
+ Sfread_f oreadf;
+ Sfwrite_f owritef;
+ Sfseek_f oseekf;
+ ssize_t n;
+ Dccache_t *dcca = NIL(Dccache_t*);
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, NIL(Sfdisc_t*));
+
+ if((Sfio_t*)disc == f) /* special case to get the top discipline */
+ SFMTXRETURN(f,f->disc);
+
+ if((f->flags&SF_READ) && f->proc && (f->mode&SF_WRITE) )
+ { /* make sure in read mode to check for read-ahead data */
+ if(_sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, NIL(Sfdisc_t*));
+ }
+ else
+ { if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ SFMTXRETURN(f, NIL(Sfdisc_t*));
+ }
+
+ SFLOCK(f,0);
+ rdisc = NIL(Sfdisc_t*);
+
+ /* disallow popping while there is cached data */
+ if(!disc && f->disc && f->disc->disc && f->disc->disc->readf == _dccaread )
+ goto done;
+
+ /* synchronize before switching to a new discipline */
+ if(!(f->flags&SF_STRING))
+ { (void)SFSYNC(f); /* do a silent buffer synch */
+ if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
+ { f->mode &= ~SF_SYNCED;
+ f->endb = f->next = f->endr = f->endw = f->data;
+ }
+
+ /* if there is buffered data, ask app before proceeding */
+ if(((f->mode&SF_WRITE) && (n = f->next-f->data) > 0) ||
+ ((f->mode&SF_READ) && (n = f->endb-f->next) > 0) )
+ { int rv = 0;
+ if(rv == 0 && f->disc && f->disc->exceptf) /* ask current discipline */
+ { SFOPEN(f,0);
+ rv = (*f->disc->exceptf)(f, SF_DBUFFER, &n, f->disc);
+ SFLOCK(f,0);
+ }
+ if(rv == 0 && disc && disc->exceptf) /* ask discipline being pushed */
+ { SFOPEN(f,0);
+ rv = (*disc->exceptf)(f, SF_DBUFFER, &n, disc);
+ SFLOCK(f,0);
+ }
+ if(rv < 0)
+ goto done;
+ }
+
+ /* trick the new discipline into processing already buffered data */
+ if((f->mode&SF_READ) && n > 0 && disc && disc->readf )
+ { if(!(dcca = (Dccache_t*)malloc(sizeof(Dccache_t)+n)) )
+ goto done;
+ memclear(dcca, sizeof(Dccache_t));
+
+ dcca->disc.readf = _dccaread;
+ dcca->disc.exceptf = _dccaexcept;
+
+ /* move buffered data into the temp discipline */
+ dcca->data = ((uchar*)dcca) + sizeof(Dccache_t);
+ dcca->endb = dcca->data + n;
+ memcpy(dcca->data, f->next, n);
+ f->endb = f->next = f->endr = f->endw = f->data;
+ }
+ }
+
+ /* save old readf, writef, and seekf to see if stream need reinit */
+#define GETDISCF(func,iof,type) \
+ { for(d = f->disc; d && !d->iof; d = d->disc) ; \
+ func = d ? d->iof : NIL(type); \
+ }
+ GETDISCF(oreadf,readf,Sfread_f);
+ GETDISCF(owritef,writef,Sfwrite_f);
+ GETDISCF(oseekf,seekf,Sfseek_f);
+
+ if(disc == SF_POPDISC)
+ { /* popping, warn the being popped discipline */
+ if(!(d = f->disc) )
+ goto done;
+ disc = d->disc;
+ if(d->exceptf)
+ { SFOPEN(f,0);
+ if((*(d->exceptf))(f,SF_DPOP,(Void_t*)disc,d) < 0 )
+ goto done;
+ SFLOCK(f,0);
+ }
+ f->disc = disc;
+ rdisc = d;
+ }
+ else
+ { /* pushing, warn being pushed discipline */
+ do
+ { /* loop to handle the case where d may pop itself */
+ d = f->disc;
+ if(d && d->exceptf)
+ { SFOPEN(f,0);
+ if( (*(d->exceptf))(f,SF_DPUSH,(Void_t*)disc,d) < 0 )
+ goto done;
+ SFLOCK(f,0);
+ }
+ } while(d != f->disc);
+
+ /* make sure we are not creating an infinite loop */
+ for(; d; d = d->disc)
+ if(d == disc)
+ goto done;
+
+ /* set new disc */
+ if(dcca) /* insert the discipline with cached data */
+ { dcca->disc.disc = f->disc;
+ disc->disc = &dcca->disc;
+ }
+ else disc->disc = f->disc;
+ f->disc = disc;
+ rdisc = disc;
+ }
+
+ if(!(f->flags&SF_STRING) )
+ { /* this stream may have to be reinitialized */
+ reg int reinit = 0;
+#define DISCF(dst,iof,type) (dst ? dst->iof : NIL(type))
+#define REINIT(oiof,iof,type) \
+ if(!reinit) \
+ { for(d = f->disc; d && !d->iof; d = d->disc) ; \
+ if(DISCF(d,iof,type) != oiof) \
+ reinit = 1; \
+ }
+
+ REINIT(oreadf,readf,Sfread_f);
+ REINIT(owritef,writef,Sfwrite_f);
+ REINIT(oseekf,seekf,Sfseek_f);
+
+ if(reinit)
+ { SETLOCAL(f);
+ f->bits &= ~SF_NULL; /* turn off /dev/null handling */
+ if((f->bits&SF_MMAP) || (f->mode&SF_INIT))
+ sfsetbuf(f,NIL(Void_t*),(size_t)SF_UNBOUND);
+ else if(f->data == f->tiny)
+ sfsetbuf(f,NIL(Void_t*),0);
+ else
+ { int flags = f->flags;
+ sfsetbuf(f,(Void_t*)f->data,f->size);
+ f->flags |= (flags&SF_MALLOC);
+ }
+ }
+ }
+
+done :
+ SFOPEN(f,0);
+ SFMTXRETURN(f, rdisc);
+}
diff --git a/src/lib/libast/sfio/sfdlen.c b/src/lib/libast/sfio/sfdlen.c
new file mode 100644
index 0000000..69d6cb4
--- /dev/null
+++ b/src/lib/libast/sfio/sfdlen.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Return the length of a double value if coded in a portable format
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sfdlen(Sfdouble_t v)
+#else
+int _sfdlen(v)
+Sfdouble_t v;
+#endif
+{
+#define N_ARRAY (16*sizeof(Sfdouble_t))
+ reg int n, w;
+ Sfdouble_t x;
+ int exp;
+
+ if(v < 0)
+ v = -v;
+
+ /* make the magnitude of v < 1 */
+ if(v != 0.)
+ v = frexpl(v,&exp);
+ else exp = 0;
+
+ for(w = 1; w <= N_ARRAY; ++w)
+ { /* get 2^SF_PRECIS precision at a time */
+ n = (int)(x = ldexpl(v,SF_PRECIS));
+ v = x-n;
+ if(v <= 0.)
+ break;
+ }
+
+ return 1 + sfulen(exp) + w;
+}
diff --git a/src/lib/libast/sfio/sfecvt.c b/src/lib/libast/sfio/sfecvt.c
new file mode 100644
index 0000000..35d034b
--- /dev/null
+++ b/src/lib/libast/sfio/sfecvt.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#if __STD_C
+char* sfecvt(double dval, int n_digit, int* decpt, int* sign)
+#else
+char* sfecvt(dval,n_digit,decpt,sign)
+double dval; /* value to convert */
+int n_digit; /* number of digits wanted */
+int* decpt; /* to return decimal point */
+int* sign; /* to return sign */
+#endif
+{
+ int len;
+ static char buf[SF_MAXDIGITS];
+
+ return _sfcvt(&dval,buf,sizeof(buf),n_digit,decpt,sign,&len,SFFMT_EFORMAT);
+}
diff --git a/src/lib/libast/sfio/sfexcept.c b/src/lib/libast/sfio/sfexcept.c
new file mode 100644
index 0000000..fc08d6e
--- /dev/null
+++ b/src/lib/libast/sfio/sfexcept.c
@@ -0,0 +1,133 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Function to handle io exceptions.
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sfexcept(Sfio_t* f, int type, ssize_t io, Sfdisc_t* disc)
+#else
+int _sfexcept(f,type,io,disc)
+Sfio_t* f; /* stream where the exception happened */
+int type; /* io type that was performed */
+ssize_t io; /* the io return value that indicated exception */
+Sfdisc_t* disc; /* discipline in use */
+#endif
+{
+ reg int ev, local, lock;
+ reg ssize_t size;
+ reg uchar* data;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+ lock = f->mode&SF_LOCK;
+
+ if(local && io <= 0)
+ f->flags |= io < 0 ? SF_ERROR : SF_EOF;
+
+ if(disc && disc->exceptf)
+ { /* let the stream be generally accessible for this duration */
+ if(local && lock)
+ SFOPEN(f,0);
+
+ /* so that exception handler knows what we are asking for */
+ _Sfi = f->val = io;
+ ev = (*(disc->exceptf))(f,type,&io,disc);
+
+ /* relock if necessary */
+ if(local && lock)
+ SFLOCK(f,0);
+
+ if(io > 0 && !(f->flags&SF_STRING) )
+ SFMTXRETURN(f, ev);
+ if(ev < 0)
+ SFMTXRETURN(f, SF_EDONE);
+ if(ev > 0)
+ SFMTXRETURN(f, SF_EDISC);
+ }
+
+ if(f->flags&SF_STRING)
+ { if(type == SF_READ)
+ goto chk_stack;
+ else if(type != SF_WRITE && type != SF_SEEK)
+ SFMTXRETURN(f, SF_EDONE);
+ if(local && io >= 0)
+ { if(f->size >= 0 && !(f->flags&SF_MALLOC))
+ goto chk_stack;
+ /* extend buffer */
+ if((size = f->size) < 0)
+ size = 0;
+ if((io -= size) <= 0)
+ io = SF_GRAIN;
+ size = ((size+io+SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
+ if(f->size > 0)
+ data = (uchar*)realloc((char*)f->data,size);
+ else data = (uchar*)malloc(size);
+ if(!data)
+ goto chk_stack;
+ f->endb = data + size;
+ f->next = data + (f->next - f->data);
+ f->endr = f->endw = f->data = data;
+ f->size = size;
+ }
+ SFMTXRETURN(f, SF_EDISC);
+ }
+
+ if(errno == EINTR)
+ { if(_Sfexiting || (f->bits&SF_ENDING) || /* stop being a hero */
+ (f->flags&SF_IOINTR) ) /* application requests to return */
+ SFMTXRETURN(f, SF_EDONE);
+
+ /* a normal interrupt, we can continue */
+ errno = 0;
+ f->flags &= ~(SF_EOF|SF_ERROR);
+ SFMTXRETURN(f, SF_ECONT);
+ }
+
+chk_stack:
+ if(local && f->push &&
+ ((type == SF_READ && f->next >= f->endb) ||
+ (type == SF_WRITE && f->next <= f->data)))
+ { /* pop the stack */
+ reg Sfio_t *pf;
+
+ if(lock)
+ SFOPEN(f,0);
+
+ /* pop and close */
+ pf = (*_Sfstack)(f,NIL(Sfio_t*));
+ if((ev = sfclose(pf)) < 0) /* can't close, restack */
+ (*_Sfstack)(f,pf);
+
+ if(lock)
+ SFLOCK(f,0);
+
+ ev = ev < 0 ? SF_EDONE : SF_ESTACK;
+ }
+ else ev = SF_EDONE;
+
+ SFMTXRETURN(f, ev);
+}
diff --git a/src/lib/libast/sfio/sfextern.c b/src/lib/libast/sfio/sfextern.c
new file mode 100644
index 0000000..e5f2c6e
--- /dev/null
+++ b/src/lib/libast/sfio/sfextern.c
@@ -0,0 +1,99 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* External variables and functions used only by Sfio
+** Written by Kiem-Phong Vo
+*/
+
+/* code to initialize mutexes */
+static Vtmutex_t Sfmutex;
+static Vtonce_t Sfonce = VTONCE_INITDATA;
+static void _sfoncef()
+{ (void)vtmtxopen(_Sfmutex, VT_INIT);
+ (void)vtmtxopen(&_Sfpool.mutex, VT_INIT);
+ (void)vtmtxopen(sfstdin->mutex, VT_INIT);
+ (void)vtmtxopen(sfstdout->mutex, VT_INIT);
+ (void)vtmtxopen(sfstderr->mutex, VT_INIT);
+ _Sfdone = 1;
+}
+
+/* global variables used internally to the package */
+Sfextern_t _Sfextern =
+{ 0, /* _Sfpage */
+ { NIL(Sfpool_t*), 0, 0, 0, NIL(Sfio_t**) }, /* _Sfpool */
+ NIL(int(*)_ARG_((Sfio_t*,int))), /* _Sfpmove */
+ NIL(Sfio_t*(*)_ARG_((Sfio_t*, Sfio_t*))), /* _Sfstack */
+ NIL(void(*)_ARG_((Sfio_t*, int, void*))), /* _Sfnotify */
+ NIL(int(*)_ARG_((Sfio_t*))), /* _Sfstdsync */
+ { NIL(Sfread_f), /* _Sfudisc */
+ NIL(Sfwrite_f),
+ NIL(Sfseek_f),
+ NIL(Sfexcept_f),
+ NIL(Sfdisc_t*)
+ },
+ NIL(void(*)_ARG_((void)) ), /* _Sfcleanup */
+ 0, /* _Sfexiting */
+ 0, /* _Sfdone */
+ &Sfonce, /* _Sfonce */
+ _sfoncef, /* _Sfoncef */
+ &Sfmutex /* _Sfmutex */
+};
+
+ssize_t _Sfi = -1; /* value for a few fast macro functions */
+ssize_t _Sfmaxr = 0; /* default (unlimited) max record size */
+
+#if vt_threaded
+static Vtmutex_t _Sfmtxin, _Sfmtxout, _Sfmtxerr;
+#define SFMTXIN (&_Sfmtxin)
+#define SFMTXOUT (&_Sfmtxout)
+#define SFMTXERR (&_Sfmtxerr)
+#define SF_STDSAFE SF_MTSAFE
+#else
+#define SFMTXIN (0)
+#define SFMTXOUT (0)
+#define SFMTXERR (0)
+#define SF_STDSAFE (0)
+#endif
+
+Sfio_t _Sfstdin = SFNEW(NIL(char*),-1,0,
+ (SF_READ |SF_STATIC|SF_STDSAFE),NIL(Sfdisc_t*),SFMTXIN);
+Sfio_t _Sfstdout = SFNEW(NIL(char*),-1,1,
+ (SF_WRITE|SF_STATIC|SF_STDSAFE),NIL(Sfdisc_t*),SFMTXOUT);
+Sfio_t _Sfstderr = SFNEW(NIL(char*),-1,2,
+ (SF_WRITE|SF_STATIC|SF_STDSAFE),NIL(Sfdisc_t*),SFMTXERR);
+
+#undef sfstdin
+#undef sfstdout
+#undef sfstderr
+
+Sfio_t* sfstdin = &_Sfstdin;
+Sfio_t* sfstdout = &_Sfstdout;
+Sfio_t* sfstderr = &_Sfstderr;
+
+__EXTERN__(ssize_t,_Sfi);
+__EXTERN__(Sfio_t,_Sfstdin);
+__EXTERN__(Sfio_t,_Sfstdout);
+__EXTERN__(Sfio_t,_Sfstderr);
+__EXTERN__(Sfio_t*,sfstdin);
+__EXTERN__(Sfio_t*,sfstdout);
+__EXTERN__(Sfio_t*,sfstderr);
diff --git a/src/lib/libast/sfio/sffcvt.c b/src/lib/libast/sfio/sffcvt.c
new file mode 100644
index 0000000..ade6d5e
--- /dev/null
+++ b/src/lib/libast/sfio/sffcvt.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#if __STD_C
+char *sffcvt(double dval, int n_digit, int* decpt, int* sign)
+#else
+char *sffcvt(dval,n_digit,decpt,sign)
+double dval; /* value to convert */
+int n_digit; /* number of digits wanted */
+int* decpt; /* to return decimal point */
+int* sign; /* to return sign */
+#endif
+{
+ int len;
+ static char buf[SF_MAXDIGITS];
+
+ return _sfcvt(&dval,buf,sizeof(buf),n_digit,decpt,sign,&len,0);
+}
diff --git a/src/lib/libast/sfio/sffilbuf.c b/src/lib/libast/sfio/sffilbuf.c
new file mode 100644
index 0000000..16d5e3a
--- /dev/null
+++ b/src/lib/libast/sfio/sffilbuf.c
@@ -0,0 +1,116 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Fill the buffer of a stream with data.
+** If n < 0, sffilbuf() attempts to fill the buffer if it's empty.
+** If n == 0, if the buffer is not empty, just return the first byte;
+** otherwise fill the buffer and return the first byte.
+** If n > 0, even if the buffer is not empty, try a read to get as
+** close to n as possible. n is reset to -1 if stack pops.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sffilbuf(Sfio_t* f, reg int n)
+#else
+int _sffilbuf(f,n)
+Sfio_t* f; /* fill the read buffer of this stream */
+reg int n; /* see above */
+#endif
+{
+ reg ssize_t r;
+ reg int first, local, rcrv, rc, justseek;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+
+ /* any peek data must be preserved across stacked streams */
+ rcrv = f->mode&(SF_RC|SF_RV|SF_LOCK);
+ rc = f->getr;
+
+ justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK;
+
+ for(first = 1;; first = 0, (f->mode &= ~SF_LOCK) )
+ { /* check mode */
+ if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0)
+ SFMTXRETURN(f,-1);
+ SFLOCK(f,local);
+
+ /* current extent of available data */
+ if((r = f->endb-f->next) > 0)
+ { /* on first iteration, n is amount beyond current buffer;
+ afterward, n is the exact amount requested */
+ if((first && n <= 0) || (!first && n <= r) ||
+ (f->flags&SF_STRING))
+ break;
+
+ /* try shifting left to make room for new data */
+ if(!(f->bits&SF_MMAP) && f->next > f->data &&
+ n > (f->size - (f->endb-f->data)) )
+ { ssize_t s = r;
+
+ /* try to maintain block alignment */
+ if(f->blksz > 0 && (f->here%f->blksz) == 0 )
+ { s = ((r + f->blksz-1)/f->blksz)*f->blksz;
+ if(s+n > f->size)
+ s = r;
+ }
+
+ memmove(f->data, f->endb-s, s);
+ f->next = f->data + (s-r);
+ f->endb = f->data + s;
+ }
+ }
+ else if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) )
+ f->next = f->endb = f->endr = f->data;
+
+ if(f->bits&SF_MMAP)
+ r = n > 0 ? n : f->size;
+ else if(!(f->flags&SF_STRING) )
+ { r = f->size - (f->endb - f->data); /* available buffer */
+ if(n > 0)
+ { if(r > n && f->extent < 0 && (f->flags&SF_SHARE) )
+ r = n; /* read only as much as requested */
+ else if(justseek && n <= f->iosz && f->iosz <= f->size)
+ r = f->iosz; /* limit buffer filling */
+ }
+ }
+
+ /* SFRD takes care of discipline read and stack popping */
+ f->mode |= rcrv;
+ f->getr = rc;
+ if((r = SFRD(f,f->endb,r,f->disc)) >= 0)
+ { r = f->endb - f->next;
+ break;
+ }
+ }
+
+ SFOPEN(f,local);
+
+ rcrv = (n == 0) ? (r > 0 ? (int)(*f->next++) : EOF) : (int)r;
+
+ SFMTXRETURN(f,rcrv);
+}
diff --git a/src/lib/libast/sfio/sfflsbuf.c b/src/lib/libast/sfio/sfflsbuf.c
new file mode 100644
index 0000000..36d78dc
--- /dev/null
+++ b/src/lib/libast/sfio/sfflsbuf.c
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write a buffer out to a file descriptor or
+** extending a buffer for a SF_STRING stream.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sfflsbuf(Sfio_t* f, int c)
+#else
+int _sfflsbuf(f,c)
+Sfio_t* f; /* write out the buffered content of this stream */
+int c; /* if c>=0, c is also written out */
+#endif
+{
+ ssize_t n, w, written;
+ uchar* data;
+ uchar outc;
+ int local, isall;
+ int inpc = c;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+
+ for(written = 0;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,local);
+
+ /* current data extent */
+ n = f->next - (data = f->data);
+
+ if(n == (f->endb-data) && (f->flags&SF_STRING))
+ { /* call sfwr() to extend string buffer and process events */
+ w = ((f->bits&SF_PUTR) && f->val > 0) ? f->val : 1;
+ (void)SFWR(f, data, w, f->disc);
+
+ /* !(f->flags&SF_STRING) is required because exception
+ handlers may turn a string stream to a file stream */
+ if(f->next < f->endb || !(f->flags&SF_STRING) )
+ n = f->next - (data = f->data);
+ else
+ { SFOPEN(f,local);
+ SFMTXRETURN(f, -1);
+ }
+ }
+
+ if(c >= 0)
+ { /* write into buffer */
+ if(n < (f->endb - (data = f->data)))
+ { *f->next++ = c;
+ if(c == '\n' &&
+ (f->flags&SF_LINE) && !(f->flags&SF_STRING))
+ { c = -1;
+ n += 1;
+ }
+ else break;
+ }
+ else if(n == 0)
+ { /* unbuffered io */
+ outc = (uchar)c;
+ data = &outc;
+ c = -1;
+ n = 1;
+ }
+ }
+
+ if(n == 0 || (f->flags&SF_STRING))
+ break;
+
+ isall = SFISALL(f,isall);
+ if((w = SFWR(f,data,n,f->disc)) > 0)
+ { if((n -= w) > 0) /* save unwritten data, then resume */
+ memcpy((char*)f->data,(char*)data+w,n);
+ written += w;
+ f->next = f->data+n;
+ if(c < 0 && (!isall || n == 0))
+ break;
+ }
+ else if(w == 0)
+ { if(written > 0) /* some buffer was cleared */
+ break; /* do normal exit below */
+ else /* nothing was done, returning failure */
+ { SFOPEN(f,local);
+ SFMTXRETURN(f, -1);
+ }
+ }
+ else /* w < 0 means SF_EDISC or SF_ESTACK in sfwr() */
+ { if(c < 0) /* back to the calling write operation */
+ break;
+ else continue; /* try again to write out c */
+ }
+ }
+
+ SFOPEN(f,local);
+
+ if(inpc < 0)
+ inpc = f->endb-f->next;
+
+ SFMTXRETURN(f,inpc);
+}
diff --git a/src/lib/libast/sfio/sfgetd.c b/src/lib/libast/sfio/sfgetd.c
new file mode 100644
index 0000000..8c885c9
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetd.c
@@ -0,0 +1,79 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read a portably coded double value
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sfdouble_t sfgetd(Sfio_t* f)
+#else
+Sfdouble_t sfgetd(f)
+Sfio_t* f;
+#endif
+{
+ reg uchar *s, *ends, c;
+ reg int p, sign, exp;
+ Sfdouble_t v;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1.);
+
+ if((sign = sfgetc(f)) < 0 || (exp = (int)sfgetu(f)) < 0)
+ SFMTXRETURN(f, -1.);
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, -1.);
+
+ SFLOCK(f,0);
+
+ v = 0.;
+ for(;;)
+ { /* fast read for data */
+ if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = -1.;
+ goto done;
+ }
+
+ for(ends = s+p; s < ends; )
+ { c = *s++;
+ v += SFUVALUE(c);
+ v = ldexpl(v,-SF_PRECIS);
+ if(!(c&SF_MORE))
+ { f->next = s;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+
+done:
+ v = ldexpl(v,(sign&02) ? -exp : exp);
+ if(sign&01)
+ v = -v;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfgetl.c b/src/lib/libast/sfio/sfgetl.c
new file mode 100644
index 0000000..bc83229
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetl.c
@@ -0,0 +1,70 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read a long value coded in a portable format.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sflong_t sfgetl(Sfio_t* f)
+#else
+Sflong_t sfgetl(f)
+Sfio_t* f;
+#endif
+{
+ Sflong_t v;
+ uchar *s, *ends, c;
+ int p;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,(Sflong_t)(-1));
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, (Sflong_t)(-1));
+ SFLOCK(f,0);
+
+ for(v = 0;;)
+ { if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = (Sflong_t)(-1);
+ goto done;
+ }
+ for(ends = s+p; s < ends;)
+ { c = *s++;
+ if(c&SF_MORE)
+ v = ((Sfulong_t)v << SF_UBITS) | SFUVALUE(c);
+ else
+ { /* special translation for this byte */
+ v = ((Sfulong_t)v << SF_SBITS) | SFSVALUE(c);
+ f->next = s;
+ v = (c&SF_SIGN) ? -v-1 : v;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+done :
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfgetm.c b/src/lib/libast/sfio/sfgetm.c
new file mode 100644
index 0000000..16598eb
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetm.c
@@ -0,0 +1,68 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read an unsigned long value coded portably for a given range.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sfulong_t sfgetm(Sfio_t* f, Sfulong_t m)
+#else
+Sfulong_t sfgetm(f, m)
+Sfio_t* f;
+Sfulong_t m;
+#endif
+{
+ Sfulong_t v;
+ reg uchar *s, *ends, c;
+ reg int p;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfulong_t)(-1));
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, (Sfulong_t)(-1));
+
+ SFLOCK(f,0);
+
+ for(v = 0;; )
+ { if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = (Sfulong_t)(-1);
+ goto done;
+ }
+ for(ends = s+p; s < ends;)
+ { c = *s++;
+ v = (v << SF_BBITS) | SFBVALUE(c);
+ if((m >>= SF_BBITS) <= 0)
+ { f->next = s;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+done:
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfgetr.c b/src/lib/libast/sfio/sfgetr.c
new file mode 100644
index 0000000..a3b9d34
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetr.c
@@ -0,0 +1,169 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read a record delineated by a character.
+** The record length can be accessed via sfvalue(f).
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+char* sfgetr(Sfio_t *f, int rc, int type)
+#else
+char* sfgetr(f,rc,type)
+Sfio_t* f; /* stream to read from */
+int rc; /* record separator */
+int type;
+#endif
+{
+ ssize_t n, un;
+ uchar *s, *ends, *us;
+ int found;
+ Sfrsrv_t* rsrv;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, NIL(char*));
+
+ if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) )
+ SFMTXRETURN(f, NIL(char*));
+ SFLOCK(f,0);
+
+ /* buffer to be returned */
+ rsrv = NIL(Sfrsrv_t*);
+ us = NIL(uchar*);
+ un = 0;
+ found = 0;
+
+ /* compatibility mode */
+ type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type;
+
+ if(type&SF_LASTR) /* return the broken record */
+ { if((f->flags&SF_STRING) && (un = f->endb - f->next))
+ { us = f->next;
+ f->next = f->endb;
+ found = 1;
+ }
+ else if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0)
+ { us = rsrv->data;
+ found = 1;
+ }
+ goto done;
+ }
+
+ while(!found)
+ { /* fill buffer if necessary */
+ if((n = (ends = f->endb) - (s = f->next)) <= 0)
+ { /* for unseekable devices, peek-read 1 record */
+ f->getr = rc;
+ f->mode |= SF_RC;
+
+ /* fill buffer the conventional way */
+ if(SFRPEEK(f,s,n) <= 0)
+ { us = NIL(uchar*);
+ goto done;
+ }
+ else
+ { ends = s+n;
+ if(f->mode&SF_RC)
+ { s = ends[-1] == rc ? ends-1 : ends;
+ goto do_copy;
+ }
+ }
+ }
+
+#if _lib_memchr
+ if(!(s = (uchar*)memchr((char*)s,rc,n)))
+ s = ends;
+#else
+ while(*s != rc)
+ if((s += 1) == ends)
+ break;
+#endif
+ do_copy:
+ if(s < ends) /* found separator */
+ { s += 1; /* include the separator */
+ found = 1;
+
+ if(!us &&
+ (!(type&SF_STRING) || !(f->flags&SF_STRING) ||
+ ((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) )
+ { /* returning data in buffer */
+ us = f->next;
+ un = s - f->next;
+ f->next = s;
+ goto done;
+ }
+ }
+
+ /* amount to be read */
+ n = s - f->next;
+
+ if(!found && (_Sfmaxr > 0 && un+n+1 >= _Sfmaxr || (f->flags&SF_STRING))) /* already exceed limit */
+ { us = NIL(uchar*);
+ goto done;
+ }
+
+ /* get internal buffer */
+ if(!rsrv || rsrv->size < un+n+1)
+ { if(rsrv)
+ rsrv->slen = un;
+ if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*))
+ us = rsrv->data;
+ else
+ { us = NIL(uchar*);
+ goto done;
+ }
+ }
+
+ /* now copy data */
+ s = us+un;
+ un += n;
+ ends = f->next;
+ f->next += n;
+ MEMCPY(s,ends,n);
+ }
+
+done:
+ _Sfi = f->val = un;
+ f->getr = 0;
+ if(found && rc != 0 && (type&SF_STRING) )
+ { us[un-1] = '\0';
+ if(us >= f->data && us < f->endb)
+ { f->getr = rc;
+ f->mode |= SF_GETR;
+ }
+ }
+
+ /* prepare for a call to get the broken record */
+ if(rsrv)
+ rsrv->slen = found ? 0 : -un;
+
+ SFOPEN(f,0);
+
+ if(us && (type&SF_LOCKR) )
+ { f->mode |= SF_PEEK|SF_GETR;
+ f->endr = f->data;
+ }
+
+ SFMTXRETURN(f, (char*)us);
+}
diff --git a/src/lib/libast/sfio/sfgetu.c b/src/lib/libast/sfio/sfgetu.c
new file mode 100644
index 0000000..d0d6b5f
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetu.c
@@ -0,0 +1,67 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read an unsigned long value coded in a portable format.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sfulong_t sfgetu(Sfio_t* f)
+#else
+Sfulong_t sfgetu(f)
+Sfio_t* f;
+#endif
+{
+ Sfulong_t v;
+ uchar *s, *ends, c;
+ int p;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, (Sfulong_t)(-1));
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, (Sfulong_t)(-1));
+
+ SFLOCK(f,0);
+
+ for(v = 0;;)
+ { if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = (Sfulong_t)(-1);
+ goto done;
+ }
+ for(ends = s+p; s < ends;)
+ { c = *s++;
+ v = (v << SF_UBITS) | SFUVALUE(c);
+ if(!(c&SF_MORE))
+ { f->next = s;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+done:
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfhdr.h b/src/lib/libast/sfio/sfhdr.h
new file mode 100644
index 0000000..d5f15cf
--- /dev/null
+++ b/src/lib/libast/sfio/sfhdr.h
@@ -0,0 +1,1302 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _SFHDR_H
+#define _SFHDR_H 1
+#if !defined(_BLD_sfio) && !defined(_BLD_stdio)
+#define _BLD_sfio 1
+#endif
+
+/* Internal definitions for sfio.
+** Written by Kiem-Phong Vo
+*/
+
+#define _next next
+#define _endw endw
+#define _endr endr
+#define _endb endb
+#define _push push
+#define _flags flags
+#define _file file
+#define _data data
+#define _size size
+#define _val val
+
+#include "FEATURE/sfio"
+#include "FEATURE/mmap"
+
+/* define va_list, etc. before including sfio_t.h (sfio.h) */
+#if !_PACKAGE_ast
+
+/* some systems don't know large files */
+#if defined(_NO_LARGEFILE64_SOURCE) || _mips == 2 /* || __hppa */
+#undef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#undef _LARGEFILE64_SOURCE
+#undef _LARGEFILE_SOURCE
+#endif
+
+#if !_NO_LARGEFILE64_SOURCE && _typ_off64_t && _lib_lseek64 && _lib_stat64
+#undef _LARGEFILE64_SOURCE
+#undef _LARGEFILE_SOURCE
+#undef _FILE_OFFSET_BITS
+#define _LARGEFILE64_SOURCE 1 /* enabling the *64 stuff */
+#define _LARGEFILE_SOURCE 1
+#endif
+
+#if _hdr_stdarg
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "FEATURE/common"
+#if !__STD_C
+#define const
+#endif
+#endif /* !_PACKAGE_ast */
+
+#include "sfio_t.h"
+
+/* note that the macro vt_threaded has effect on vthread.h */
+#include <vthread.h>
+
+/* file system info */
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <ast_time.h>
+#include <ast_tty.h>
+#include <ls.h>
+
+/* ast always provides multibyte handling */
+#undef _hdr_wchar
+#undef _lib_mbrtowc
+#undef _lib_wcrtomb
+#define _hdr_wchar 1
+#define _lib_mbrtowc 1
+#define _lib_wcrtomb 1
+
+#if _mem_st_blksize_stat
+#define _stat_blksize 1
+#endif
+
+#if _lib_localeconv && _hdr_locale
+#define _lib_locale 1
+#endif
+
+#define sfoff_t off_t
+#define sfstat_t struct stat
+#define sysclosef close
+#define syscreatf creat
+#define sysdupf dup
+#define sysfcntlf fcntl
+#define sysfstatf fstat
+#define sysftruncatef ftruncate
+#define syslseekf lseek
+#define sysmmapf mmap
+#define sysmunmapf munmap
+#define sysopenf open
+#define syspipef pipe
+#define sysreadf read
+#define sysremovef remove
+#define sysstatf stat
+#define syswritef write
+
+#else /*!_PACKAGE_ast*/
+
+/* when building the binary compatibility package, a number of header files
+ are not needed and they may get in the way so we remove them here.
+*/
+#if _SFBINARY_H
+#undef _hdr_time
+#undef _sys_time
+#undef _sys_stat
+#undef _hdr_stat
+#undef _hdr_filio
+#undef _sys_filio
+#undef _lib_poll
+#undef _stream_peek
+#undef _socket_peek
+#undef _hdr_vfork
+#undef _sys_vfork
+#undef _lib_vfork
+#undef _hdr_values
+#undef _hdr_math
+#undef _sys_mman
+#undef _hdr_mman
+#undef _sys_ioctl
+#endif
+
+#if _hdr_stdlib
+#include <stdlib.h>
+#endif
+
+#if _hdr_string
+#include <string.h>
+#endif
+
+#if _hdr_time
+#include <time.h>
+#endif
+#if _sys_time
+#include <sys/time.h>
+#endif
+
+#if _sys_stat
+#include <sys/stat.h>
+#else
+#if _hdr_stat
+#include <stat.h>
+#ifndef _sys_stat
+#define _sys_stat 1
+#endif
+#endif
+#endif /*_sys_stat*/
+
+#ifndef _sys_stat
+#define _sys_stat 0
+#endif
+
+#include <fcntl.h>
+
+#ifndef F_SETFD
+#ifndef FIOCLEX
+#if _hdr_filio
+#include <filio.h>
+#else
+#if _sys_filio
+#include <sys/filio.h>
+#endif /*_sys_filio*/
+#endif /*_hdr_filio*/
+#endif /*_FIOCLEX*/
+#endif /*F_SETFD*/
+
+#if _hdr_unistd
+#include <unistd.h>
+#endif
+
+#if !_LARGEFILE64_SOURCE /* turn off the *64 stuff */
+#undef _typ_off64_t
+#undef _typ_struct_stat64
+#undef _lib_creat64
+#undef _lib_open64
+#undef _lib_close64
+#undef _lib_stat64
+#undef _lib_fstat64
+#undef _lib_ftruncate64
+#undef _lib_lseek64
+#undef _lib_mmap64
+#undef _lib_munmap64
+#endif /*!_LARGEFILE64_SOURCE */
+
+/* see if we can use memory mapping for io */
+#if _LARGEFILE64_SOURCE && !_lib_mmap64
+#undef _mmap_worthy
+#endif
+#if !_mmap_worthy
+#undef _hdr_mman
+#undef _sys_mman
+#endif
+#if _hdr_mman
+#include <mman.h>
+#endif
+#if _sys_mman
+#include <sys/mman.h>
+#endif
+
+/* standardize system calls and types dealing with files */
+#if _typ_off64_t
+#define sfoff_t off64_t
+#else
+#define sfoff_t off_t
+#endif
+#if _typ_struct_stat64
+#define sfstat_t struct stat64
+#else
+#define sfstat_t struct stat
+#endif
+#if _lib_lseek64
+#define syslseekf lseek64
+#else
+#define syslseekf lseek
+#endif
+#if _lib_stat64
+#define sysstatf stat64
+#else
+#define sysstatf stat
+#endif
+#if _lib_fstat64
+#define sysfstatf fstat64
+#else
+#define sysfstatf fstat
+#endif
+#if _lib_mmap64
+#define sysmmapf mmap64
+#else
+#define sysmmapf mmap
+#endif
+#if _lib_munmap64
+#define sysmunmapf munmap64
+#else
+#define sysmunmapf munmap
+#endif
+#if _lib_open64
+#define sysopenf open64
+#else
+#define sysopenf open
+#endif
+#if _lib_creat64
+#define syscreatf creat64
+#else
+#define syscreatf creat
+#endif
+#if _lib_close64
+#define sysclosef close64
+#else
+#define sysclosef close
+#endif
+#if _lib_ftruncate64
+#undef _lib_ftruncate
+#define _lib_ftruncate 1
+#define sysftruncatef ftruncate64
+#endif
+#if !_lib_ftruncate64 && _lib_ftruncate
+#define sysftruncatef ftruncate
+#endif
+#if _lib_remove
+#define sysremovef remove
+#else
+#define sysremovef unlink
+#endif
+
+#define sysreadf read
+#define syswritef write
+#define syspipef pipe
+#define sysdupf dup
+#define sysfcntlf fcntl
+
+#endif /*_PACKAGE_ast*/
+
+#if !_mmap_worthy
+#undef MAP_TYPE
+#endif
+
+#include "FEATURE/float"
+
+#include <errno.h>
+#include <ctype.h>
+
+/* deal with multi-byte character and string conversions */
+#if _PACKAGE_ast
+
+#include <wchar.h>
+
+#define _has_multibyte 1
+
+#define SFMBMAX mbmax()
+#define SFMBCPY(to,fr) memcpy((to), (fr), sizeof(mbstate_t))
+#define SFMBCLR(mb) memset((mb), 0, sizeof(mbstate_t))
+#define SFMBSET(lhs,v) (lhs = (v))
+#define SFMBLEN(s,mb) mbsize(s)
+#define SFMBDCL(ms) mbstate_t ms;
+
+#else
+
+#if _hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc
+#define _has_multibyte 1 /* Xopen-compliant */
+#if _typ___va_list && !defined(__va_list)
+#define __va_list va_list
+#endif
+#include <wchar.h>
+#define SFMBCPY(to,fr) memcpy((to), (fr), sizeof(mbstate_t))
+#define SFMBCLR(mb) memset((mb), 0, sizeof(mbstate_t))
+#define SFMBSET(lhs,v) (lhs = (v))
+#define SFMBDCL(mb) mbstate_t mb;
+#define SFMBLEN(s,mb) mbrtowc(NIL(wchar_t*), (s), SFMBMAX, (mb) )
+#endif /*_hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc*/
+
+#if !_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb
+#define _has_multibyte 2 /* no shift states */
+#include <wchar.h>
+#undef mbrtowc
+#define mbrtowc(wp,s,n,mb) mbtowc(wp, s, n)
+#undef wcrtomb
+#define wcrtomb(s,wc,mb) wctomb(s, wc)
+#define SFMBCPY(to,fr)
+#define SFMBCLR(mb)
+#define SFMBSET(lhs,v)
+#define SFMBDCL(mb)
+#define SFMBLEN(s,mb) mbrtowc(NIL(wchar_t*), (s), SFMBMAX, (mb) )
+#endif /*!_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb*/
+
+#ifdef MB_CUR_MAX
+#define SFMBMAX MB_CUR_MAX
+#else
+#define SFMBMAX sizeof(Sflong_t)
+#endif
+
+#endif /* _PACKAGE_ast */
+
+#if !_has_multibyte
+#define _has_multibyte 0 /* no multibyte support */
+#define SFMBCPY(to,fr)
+#define SFMBCLR(mb)
+#define SFMBSET(lhs,v)
+#define SFMBLEN(s,mb) (*(s) ? 1 : 0)
+#define SFMBDCL(mb)
+#endif /* _has_multibyte */
+
+/* dealing with streams that might be accessed concurrently */
+#if vt_threaded
+
+#define SFMTXdecl(ff,_mf_) Sfio_t* _mf_ = (ff)
+#define SFMTXbegin(ff,_mf_,rv) \
+ { if((ff)->_flags&SF_MTSAFE) \
+ { (_mf_) = (ff); \
+ if(sfmutex((ff), SFMTX_LOCK) != 0) return(rv); \
+ if(_Sfnotify) \
+ { (*_Sfnotify)((_mf_), SF_MTACCESS, (Void_t*)(&(ff)) ); \
+ if(!(ff)) (ff) = (_mf_); \
+ } \
+ } \
+ }
+#define SFMTXend(ff,_mf_) \
+ { if((ff)->_flags&SF_MTSAFE) \
+ { if(_Sfnotify) \
+ (*_Sfnotify)((_mf_), SF_MTACCESS, NIL(Void_t*) ); \
+ sfmutex((ff), SFMTX_UNLOCK); \
+ (ff) = (_mf_); \
+ } \
+ }
+
+#define SFONCE() (_Sfdone ? 0 : vtonce(_Sfonce,_Sfoncef))
+
+#define SFMTXLOCK(f) (((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_LOCK) : 0)
+#define SFMTXUNLOCK(f) (((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_UNLOCK) : 0)
+
+#define SFMTXDECL(ff) SFMTXdecl((ff), _mtxf1_)
+#define SFMTXBEGIN(ff,v) { SFMTXbegin((ff), _mtxf1_, (v) ); }
+#define SFMTXEND(ff) { SFMTXend(ff, _mtxf1_); }
+#define SFMTXENTER(ff,v) { if(!(ff)) return(v); SFMTXBEGIN((ff), (v)); }
+#define SFMTXRETURN(ff,v) { SFMTXEND(ff); return(v); }
+
+#define SFMTXDECL2(ff) SFMTXdecl((ff), _mtxf2_)
+#define SFMTXBEGIN2(ff,v) { SFMTXbegin((ff), _mtxf2_, (v) ); }
+#define SFMTXEND2(ff) { SFMTXend((ff), _mtxf2_); }
+
+#define POOLMTXLOCK(p) ( vtmtxlock(&(p)->mutex) )
+#define POOLMTXUNLOCK(p) ( vtmtxunlock(&(p)->mutex) )
+#define POOLMTXENTER(p) { POOLMTXLOCK(p); }
+#define POOLMTXRETURN(p,rv) { POOLMTXUNLOCK(p); return(rv); }
+
+#else /*!vt_threaded*/
+
+#undef SF_MTSAFE /* no need to worry about thread-safety */
+#define SF_MTSAFE 0
+
+#define SFONCE() /*(0)*/
+
+#define SFMTXLOCK(f) /*(0)*/
+#define SFMTXUNLOCK(f) /*(0)*/
+
+#define SFMTXDECL(ff) /*(0)*/
+#define SFMTXBEGIN(ff,v) /*(0)*/
+#define SFMTXEND(ff) /*(0)*/
+#define SFMTXENTER(ff,v) { if(!(ff)) return(v); }
+#define SFMTXRETURN(ff,v) { return(v); }
+
+#define SFMTXDECL2(ff) /*(0)*/
+#define SFMTXBEGIN2(ff,v) /*(0)*/
+#define SFMTXEND2(ff) /*(0)*/
+
+#define POOLMTXLOCK(p)
+#define POOLMTXUNLOCK(p)
+#define POOLMTXENTER(p)
+#define POOLMTXRETURN(p,v) { return(v); }
+
+#endif /*vt_threaded*/
+
+
+/* functions for polling readiness of streams */
+#if _lib_select
+#undef _lib_poll
+#else
+#if _lib_poll_fd_1 || _lib_poll_fd_2
+#define _lib_poll 1
+#endif
+#endif /*_lib_select_*/
+
+#if _lib_poll
+#include <poll.h>
+
+#if _lib_poll_fd_1
+#define SFPOLL(pfd,n,tm) poll((pfd),(ulong)(n),(tm))
+#else
+#define SFPOLL(pfd,n,tm) poll((ulong)(n),(pfd),(tm))
+#endif
+#endif /*_lib_poll*/
+
+#if _stream_peek
+#include <stropts.h>
+#endif
+
+#if _socket_peek
+#include <sys/socket.h>
+#endif
+
+/* to test for executable access mode of a file */
+#ifndef X_OK
+#define X_OK 01
+#endif
+
+/* alternative process forking */
+#if _lib_vfork && !defined(fork) && !defined(sparc) && !defined(__sparc)
+#if _hdr_vfork
+#include <vfork.h>
+#endif
+#if _sys_vfork
+#include <sys/vfork.h>
+#endif
+#define fork vfork
+#endif
+
+/* to get rid of pesky compiler warnings */
+#if __STD_C
+#define NOTUSED(x) (void)(x)
+#else
+#define NOTUSED(x) (&x,1)
+#endif
+
+/* Private flags in the "bits" field */
+#define SF_MMAP 00000001 /* in memory mapping mode */
+#define SF_BOTH 00000002 /* both read/write */
+#define SF_HOLE 00000004 /* a hole of zero's was created */
+#define SF_NULL 00000010 /* stream is /dev/null */
+#define SF_SEQUENTIAL 00000020 /* sequential access */
+#define SF_JUSTSEEK 00000040 /* just did a sfseek */
+#define SF_PRIVATE 00000100 /* private stream to Sfio, no mutex */
+#define SF_ENDING 00000200 /* no re-io on interrupts at closing */
+#define SF_WIDE 00000400 /* in wide mode - stdio only */
+#define SF_PUTR 00001000 /* in sfputr() */
+
+/* "bits" flags that must be cleared in sfclrlock */
+#define SF_TMPBITS 00170000
+#define SF_DCDOWN 00010000 /* recurse down the discipline stack */
+
+#define SF_WCFORMAT 00020000 /* wchar_t formatting - stdio only */
+#if _has_multibyte
+#define SFWCSET(f) ((f)->bits |= SF_WCFORMAT)
+#define SFWCGET(f,v) (((v) = (f)->bits & SF_WCFORMAT), ((f)->bits &= ~SF_WCFORMAT) )
+#else
+#define SFWCSET(f)
+#define SFWCGET(f,v)
+#endif
+
+#define SF_MVSIZE 00040000 /* f->size was reset in sfmove() */
+#define SFMVSET(f) (((f)->size *= SF_NMAP), ((f)->bits |= SF_MVSIZE) )
+#define SFMVUNSET(f) (!((f)->bits&SF_MVSIZE) ? 0 : \
+ (((f)->bits &= ~SF_MVSIZE), ((f)->size /= SF_NMAP)) )
+
+#define SFCLRBITS(f) (SFMVUNSET(f), ((f)->bits &= ~SF_TMPBITS) )
+
+
+/* bits for the mode field, SF_INIT defined in sfio_t.h */
+#define SF_RC 00000010 /* peeking for a record */
+#define SF_RV 00000020 /* reserve without read or most write */
+#define SF_LOCK 00000040 /* stream is locked for io op */
+#define SF_PUSH 00000100 /* stream has been pushed */
+#define SF_POOL 00000200 /* stream is in a pool but not current */
+#define SF_PEEK 00000400 /* there is a pending peek */
+#define SF_PKRD 00001000 /* did a peek read */
+#define SF_GETR 00002000 /* did a getr on this stream */
+#define SF_SYNCED 00004000 /* stream was synced */
+#define SF_STDIO 00010000 /* given up the buffer to stdio */
+#define SF_AVAIL 00020000 /* was closed, available for reuse */
+#define SF_LOCAL 00100000 /* sentinel for a local call */
+
+#ifdef DEBUG
+#define ASSERT(p) ((p) ? 0 : (abort(),0) )
+#else
+#define ASSERT(p)
+#endif
+
+/* short-hands */
+#define NIL(t) ((t)0)
+#define reg register
+#ifndef uchar
+#define uchar unsigned char
+#endif
+#ifndef ulong
+#define ulong unsigned long
+#endif
+#ifndef uint
+#define uint unsigned int
+#endif
+#ifndef ushort
+#define ushort unsigned short
+#endif
+
+#define SECOND 1000 /* millisecond units */
+
+/* macros do determine stream types from sfstat_t data */
+#ifndef S_IFDIR
+#define S_IFDIR 0
+#endif
+#ifndef S_IFREG
+#define S_IFREG 0
+#endif
+#ifndef S_IFCHR
+#define S_IFCHR 0
+#endif
+#ifndef S_IFIFO
+#define S_IFIFO 0
+#endif
+#ifndef S_ISOCK
+#define S_ISOCK 0
+#endif
+
+#ifndef S_IFMT
+#define S_IFMT (S_IFDIR|S_IFREG|S_IFCHR|S_IFIFO|S_ISOCK)
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
+#endif
+#ifndef S_ISCHR
+#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
+#endif
+
+#ifndef S_ISFIFO
+# if S_IFIFO
+# define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) (0)
+# endif
+#endif
+
+#ifdef S_IRUSR
+#define SF_CREATMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+#else
+#define SF_CREATMODE 0666
+#endif
+
+/* set close-on-exec */
+#ifdef F_SETFD
+# ifndef FD_CLOEXEC
+# define FD_CLOEXEC 1
+# endif /*FD_CLOEXEC*/
+# define SETCLOEXEC(fd) ((void)fcntl((fd),F_SETFD,FD_CLOEXEC))
+#else
+# ifdef FIOCLEX
+# define SETCLOEXEC(fd) ((void)ioctl((fd),FIOCLEX,0))
+# else
+# define SETCLOEXEC(fd)
+# endif /*FIOCLEX*/
+#endif /*F_SETFD*/
+
+/* a couple of error number that we use, default values are like Linux */
+#ifndef EINTR
+#define EINTR 4
+#endif
+#ifndef EBADF
+#define EBADF 9
+#endif
+#ifndef EAGAIN
+#define EAGAIN 11
+#endif
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+#ifndef ESPIPE
+#define ESPIPE 29
+#endif
+
+/* function to get the decimal point for local environment */
+#if !defined(SFSETLOCALE) && _PACKAGE_ast
+#include "lclib.h"
+#define SFSETLOCALE(dp,tp) \
+ do if (*(dp) == 0) { \
+ Lc_numeric_t* lv = (Lc_numeric_t*)LCINFO(AST_LC_NUMERIC)->data; \
+ *(dp) = lv->decimal; \
+ if (tp) *(tp) = lv->thousand; \
+ } while (0)
+#endif /*!defined(SFSETLOCALE) && _PACKAGE_ast*/
+
+#if !defined(SFSETLOCALE) && _lib_locale
+#include <locale.h>
+#define SFSETLOCALE(decimal,thousand) \
+ do { struct lconv* lv; \
+ if(*(decimal) == 0) \
+ { *(decimal) = '.'; \
+ if (thousand) *(thousand) = -1; \
+ if((lv = localeconv())) \
+ { if(lv->decimal_point && *lv->decimal_point) \
+ *(decimal) = *(unsigned char*)lv->decimal_point; \
+ if(thousand && lv->thousands_sep && *lv->thousands_sep) \
+ *(thousand) = *(unsigned char*)lv->thousands_sep; \
+ } \
+ } \
+ } while (0)
+#endif /*!defined(SFSETLOCALE) && _lib_locale*/
+
+#if !defined(SFSETLOCALE)
+#define SFSETLOCALE(decimal,thousand) (*(decimal)='.')
+#endif
+
+/* stream pool structure. */
+typedef struct _sfpool_s Sfpool_t;
+struct _sfpool_s
+{ Sfpool_t* next;
+ int mode; /* type of pool */
+ int s_sf; /* size of pool array */
+ int n_sf; /* number currently in pool */
+ Sfio_t** sf; /* array of streams */
+ Sfio_t* array[3]; /* start with 3 */
+ Vtmutex_t mutex; /* mutex lock object */
+};
+
+/* reserve buffer structure */
+typedef struct _sfrsrv_s Sfrsrv_t;
+struct _sfrsrv_s
+{ ssize_t slen; /* last string length */
+ ssize_t size; /* buffer size */
+ uchar data[1]; /* data buffer */
+};
+
+/* co-process structure */
+typedef struct _sfproc_s Sfproc_t;
+struct _sfproc_s
+{ int pid; /* process id */
+ uchar* rdata; /* read data being cached */
+ int ndata; /* size of cached data */
+ int size; /* buffer size */
+ int file; /* saved file descriptor */
+ int sigp; /* sigpipe protection needed */
+};
+
+/* extensions to sfvprintf/sfvscanf */
+#define FP_SET(fp,fn) (fp < 0 ? (fn += 1) : (fn = fp) )
+#define FP_WIDTH 0
+#define FP_PRECIS 1
+#define FP_BASE 2
+#define FP_STR 3
+#define FP_SIZE 4
+#define FP_INDEX 5 /* index size */
+
+typedef struct _fmt_s Fmt_t;
+typedef struct _fmtpos_s Fmtpos_t;
+typedef union
+{ int i, *ip;
+ long l, *lp;
+ short h, *hp;
+ uint ui;
+ ulong ul;
+ ushort uh;
+ Sflong_t ll, *llp;
+ Sfulong_t lu;
+ Sfdouble_t ld;
+ double d;
+ float f;
+#if _has_multibyte
+ wchar_t wc;
+ wchar_t *ws, **wsp;
+#endif
+ char c, *s, **sp;
+ uchar uc, *us, **usp;
+ Void_t *vp;
+ Sffmt_t *ft;
+} Argv_t;
+
+struct _fmt_s
+{ char* form; /* format string */
+ va_list args; /* corresponding arglist */
+ SFMBDCL(mbs) /* multibyte parsing state */
+
+ char* oform; /* original format string */
+ va_list oargs; /* original arg list */
+ int argn; /* number of args already used */
+ Fmtpos_t* fp; /* position list */
+
+ Sffmt_t* ft; /* formatting environment */
+ Sffmtevent_f eventf; /* event function */
+ Fmt_t* next; /* stack frame pointer */
+};
+
+struct _fmtpos_s
+{ Sffmt_t ft; /* environment */
+ Argv_t argv; /* argument value */
+ int fmt; /* original format */
+ int need[FP_INDEX]; /* positions depending on */
+};
+
+#define LEFTP '('
+#define RIGHTP ')'
+#define QUOTE '\''
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#define FMTSET(ft, frm,ags, fv, sz, flgs, wid,pr,bs, ts,ns) \
+ ((ft->form = (char*)frm), va_copy(ft->args,ags), \
+ (ft->fmt = fv), (ft->size = sz), \
+ (ft->flags = (flgs&SFFMT_SET)), \
+ (ft->width = wid), (ft->precis = pr), (ft->base = bs), \
+ (ft->t_str = ts), (ft->n_str = ns) )
+#define FMTGET(ft, frm,ags, fv, sz, flgs, wid,pr,bs) \
+ ((frm = ft->form), va_copy(ags,ft->args), \
+ (fv = ft->fmt), (sz = ft->size), \
+ (flgs = (flgs&~(SFFMT_SET))|(ft->flags&SFFMT_SET)), \
+ (wid = ft->width), (pr = ft->precis), (bs = ft->base) )
+
+/* format flags&types, must coexist with those in sfio.h */
+#define SFFMT_FORBIDDEN 000077777777 /* for sfio.h only */
+#define SFFMT_EFORMAT 001000000000 /* sfcvt converting %e */
+#define SFFMT_MINUS 002000000000 /* minus sign */
+#define SFFMT_AFORMAT 004000000000 /* sfcvt converting %a */
+#define SFFMT_UPPER 010000000000 /* sfcvt converting upper */
+
+#define SFFMT_TYPES (SFFMT_SHORT|SFFMT_SSHORT | SFFMT_LONG|SFFMT_LLONG|\
+ SFFMT_LDOUBLE | SFFMT_IFLAG|SFFMT_JFLAG| \
+ SFFMT_TFLAG | SFFMT_ZFLAG )
+
+/* type of elements to be converted */
+#define SFFMT_INT 001 /* %d,%i */
+#define SFFMT_UINT 002 /* %u,o,x etc. */
+#define SFFMT_FLOAT 004 /* %f,e,g etc. */
+#define SFFMT_CHAR 010 /* %c,C */
+#define SFFMT_POINTER 020 /* %p,n,s,S */
+#define SFFMT_CLASS 040 /* %[ */
+
+/* local variables used across sf-functions */
+#define _Sfpage (_Sfextern.sf_page)
+#define _Sfpool (_Sfextern.sf_pool)
+#define _Sfpmove (_Sfextern.sf_pmove)
+#define _Sfstack (_Sfextern.sf_stack)
+#define _Sfnotify (_Sfextern.sf_notify)
+#define _Sfstdsync (_Sfextern.sf_stdsync)
+#define _Sfudisc (&(_Sfextern.sf_udisc))
+#define _Sfcleanup (_Sfextern.sf_cleanup)
+#define _Sfexiting (_Sfextern.sf_exiting)
+#define _Sfdone (_Sfextern.sf_done)
+#define _Sfonce (_Sfextern.sf_once)
+#define _Sfoncef (_Sfextern.sf_oncef)
+#define _Sfmutex (_Sfextern.sf_mutex)
+typedef struct _sfextern_s
+{ ssize_t sf_page;
+ struct _sfpool_s sf_pool;
+ int (*sf_pmove)_ARG_((Sfio_t*, int));
+ Sfio_t* (*sf_stack)_ARG_((Sfio_t*, Sfio_t*));
+ void (*sf_notify)_ARG_((Sfio_t*, int, void*));
+ int (*sf_stdsync)_ARG_((Sfio_t*));
+ struct _sfdisc_s sf_udisc;
+ void (*sf_cleanup)_ARG_((void));
+ int sf_exiting;
+ int sf_done;
+ Vtonce_t* sf_once;
+ void (*sf_oncef)_ARG_((void));
+ Vtmutex_t* sf_mutex;
+} Sfextern_t;
+
+/* get the real value of a byte in a coded long or ulong */
+#define SFUVALUE(v) (((ulong)(v))&(SF_MORE-1))
+#define SFSVALUE(v) ((( long)(v))&(SF_SIGN-1))
+#define SFBVALUE(v) (((ulong)(v))&(SF_BYTE-1))
+
+/* pick this many bits in each iteration of double encoding */
+#define SF_PRECIS 7
+
+/* grain size for buffer increment */
+#define SF_GRAIN 1024
+#define SF_PAGE ((ssize_t)(SF_GRAIN*sizeof(int)*2))
+
+/* when the buffer is empty, certain io requests may be better done directly
+ on the given application buffers. The below condition determines when.
+*/
+#define SFDIRECT(f,n) (((ssize_t)(n) >= (f)->size) || \
+ ((n) >= SF_GRAIN && (ssize_t)(n) >= (f)->size/16 ) )
+
+/* number of pages to memory map at a time */
+#if _ptr_bits >= 64
+#define SF_NMAP 1024
+#else
+#define SF_NMAP 32
+#endif
+
+#ifndef MAP_VARIABLE
+#define MAP_VARIABLE 0
+#endif
+#ifndef _mmap_fixed
+#define _mmap_fixed 0
+#endif
+
+/* set/unset sequential states for mmap */
+#if _lib_madvise && defined(MADV_SEQUENTIAL) && defined(MADV_NORMAL)
+#define SFMMSEQON(f,a,s) \
+ do { int oerrno = errno; \
+ (void)madvise((caddr_t)(a),(size_t)(s),MADV_SEQUENTIAL); \
+ errno = oerrno; \
+ } while(0)
+#define SFMMSEQOFF(f,a,s) \
+ do { int oerrno = errno; \
+ (void)madvise((caddr_t)(a),(size_t)(s),MADV_NORMAL); \
+ errno = oerrno; \
+ } while(0)
+#else
+#define SFMMSEQON(f,a,s)
+#define SFMMSEQOFF(f,a,s)
+#endif
+
+#define SFMUNMAP(f,a,s) (sysmunmapf((caddr_t)(a),(size_t)(s)), \
+ ((f)->endb = (f)->endr = (f)->endw = (f)->next = \
+ (f)->data = NIL(uchar*)) )
+
+/* safe closing function */
+#define CLOSE(f) { while(sysclosef(f) < 0 && errno == EINTR) errno = 0; }
+
+/* the bottomless bit bucket */
+#define DEVNULL "/dev/null"
+#define SFSETNULL(f) ((f)->extent = (Sfoff_t)(-1), (f)->bits |= SF_NULL)
+#define SFISNULL(f) ((f)->extent < 0 && ((f)->bits&SF_NULL) )
+
+#define SFKILL(f) ((f)->mode = (SF_AVAIL|SF_LOCK) )
+#define SFKILLED(f) (((f)->mode&(SF_AVAIL|SF_LOCK)) == (SF_AVAIL|SF_LOCK) )
+
+/* exception types */
+#define SF_EDONE 0 /* stop this operation and return */
+#define SF_EDISC 1 /* discipline says it's ok */
+#define SF_ESTACK 2 /* stack was popped */
+#define SF_ECONT 3 /* can continue normally */
+
+#define SETLOCAL(f) ((f)->mode |= SF_LOCAL)
+#define GETLOCAL(f,v) ((v) = ((f)->mode&SF_LOCAL), (f)->mode &= ~SF_LOCAL, (v))
+#define SFWRALL(f) ((f)->mode |= SF_RV)
+#define SFISALL(f,v) ((((v) = (f)->mode&SF_RV) ? ((f)->mode &= ~SF_RV) : 0), \
+ ((v) || ((f)->flags&(SF_SHARE|SF_APPENDWR|SF_WHOLE)) ) )
+#define SFSK(f,a,o,d) (SETLOCAL(f),sfsk(f,(Sfoff_t)a,o,d))
+#define SFRD(f,b,n,d) (SETLOCAL(f),sfrd(f,(Void_t*)b,n,d))
+#define SFWR(f,b,n,d) (SETLOCAL(f),sfwr(f,(Void_t*)b,n,d))
+#define SFSYNC(f) (SETLOCAL(f),sfsync(f))
+#define SFCLOSE(f) (SETLOCAL(f),sfclose(f))
+#define SFFLSBUF(f,n) (SETLOCAL(f),_sfflsbuf(f,n))
+#define SFFILBUF(f,n) (SETLOCAL(f),_sffilbuf(f,n))
+#define SFSETBUF(f,s,n) (SETLOCAL(f),sfsetbuf(f,s,n))
+#define SFWRITE(f,s,n) (SETLOCAL(f),sfwrite(f,s,n))
+#define SFREAD(f,s,n) (SETLOCAL(f),sfread(f,s,n))
+#define SFSEEK(f,p,t) (SETLOCAL(f),sfseek(f,p,t))
+#define SFNPUTC(f,c,n) (SETLOCAL(f),sfnputc(f,c,n))
+#define SFRAISE(f,e,d) (SETLOCAL(f),sfraise(f,e,d))
+
+/* lock/open a stream */
+#define SFMODE(f,l) ((f)->mode & ~(SF_RV|SF_RC|((l) ? SF_LOCK : 0)) )
+#define SFLOCK(f,l) (void)((f)->mode |= SF_LOCK, (f)->endr = (f)->endw = (f)->data)
+#define _SFOPENRD(f) ((f)->endr = ((f)->flags&SF_MTSAFE) ? (f)->data : (f)->endb)
+#define _SFOPENWR(f) ((f)->endw = ((f)->flags&(SF_MTSAFE|SF_LINE)) ? (f)->data : (f)->endb)
+#define _SFOPEN(f) ((f)->mode == SF_READ ? _SFOPENRD(f) : \
+ (f)->mode == SF_WRITE ? _SFOPENWR(f) : \
+ ((f)->endw = (f)->endr = (f)->data) )
+#define SFOPEN(f,l) (void)((l) ? 0 : \
+ ((f)->mode &= ~(SF_LOCK|SF_RC|SF_RV), _SFOPEN(f), 0) )
+
+/* check to see if the stream can be accessed */
+#define SFFROZEN(f) (((f)->mode&(SF_PUSH|SF_LOCK|SF_PEEK)) ? 1 : \
+ !((f)->mode&SF_STDIO) ? 0 : \
+ _Sfstdsync ? (*_Sfstdsync)(f) : (((f)->mode &= ~SF_STDIO),0) )
+
+
+/* set discipline code */
+#define SFDISC(f,dc,iof) \
+ { Sfdisc_t* d; \
+ if(!(dc)) \
+ d = (dc) = (f)->disc; \
+ else d = (f->bits&SF_DCDOWN) ? ((dc) = (dc)->disc) : (dc); \
+ while(d && !(d->iof)) d = d->disc; \
+ if(d) (dc) = d; \
+ }
+#define SFDCRD(f,buf,n,dc,rv) \
+ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
+ rv = (*dc->readf)(f,buf,n,dc); \
+ if(!dcdown) f->bits &= ~SF_DCDOWN; \
+ }
+#define SFDCWR(f,buf,n,dc,rv) \
+ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
+ rv = (*dc->writef)(f,buf,n,dc); \
+ if(!dcdown) f->bits &= ~SF_DCDOWN; \
+ }
+#define SFDCSK(f,addr,type,dc,rv) \
+ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
+ rv = (*dc->seekf)(f,addr,type,dc); \
+ if(!dcdown) f->bits &= ~SF_DCDOWN; \
+ }
+
+/* fast peek of a stream */
+#define _SFAVAIL(f,s,n) ((n) = (f)->endb - ((s) = (f)->next) )
+#define SFRPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \
+ ((n) = SFFILBUF(f,-1), (s) = (f)->next, (n)) )
+#define SFWPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \
+ ((n) = SFFLSBUF(f,-1), (s) = (f)->next, (n)) )
+
+/* more than this for a line buffer, we might as well flush */
+#define HIFORLINE 128
+
+/* string stream extent */
+#define SFSTRSIZE(f) { Sfoff_t s = (f)->next - (f)->data; \
+ if(s > (f)->here) \
+ { (f)->here = s; if(s > (f)->extent) (f)->extent = s; } \
+ }
+
+/* control flags for open() */
+#ifdef O_CREAT
+#define _has_oflags 1
+#else /* for example, research UNIX */
+#define _has_oflags 0
+#define O_CREAT 004
+#define O_TRUNC 010
+#define O_APPEND 020
+#define O_EXCL 040
+
+#ifndef O_RDONLY
+#define O_RDONLY 000
+#endif
+#ifndef O_WRONLY
+#define O_WRONLY 001
+#endif
+#ifndef O_RDWR
+#define O_RDWR 002
+#endif
+#endif /*O_CREAT*/
+
+#ifndef O_BINARY
+#define O_BINARY 000
+#endif
+#ifndef O_TEXT
+#define O_TEXT 000
+#endif
+#ifndef O_TEMPORARY
+#define O_TEMPORARY 000
+#endif
+
+#define SF_RADIX 64 /* maximum integer conversion base */
+
+#if _PACKAGE_ast
+#define SF_MAXINT INT_MAX
+#define SF_MAXLONG LONG_MAX
+#else
+#define SF_MAXINT ((int)(((uint)~0) >> 1))
+#define SF_MAXLONG ((long)(((ulong)~0L) >> 1))
+#endif
+
+#define SF_MAXCHAR ((uchar)(~0))
+
+/* floating point to ascii conversion */
+#define SF_MAXEXP10 6
+#define SF_MAXPOW10 (1 << SF_MAXEXP10)
+#if !_ast_fltmax_double
+#define SF_FDIGITS 1024 /* max allowed fractional digits */
+#define SF_IDIGITS (8*1024) /* max number of digits in int part */
+#else
+#define SF_FDIGITS 256 /* max allowed fractional digits */
+#define SF_IDIGITS 1024 /* max number of digits in int part */
+#endif
+#define SF_MAXDIGITS (((SF_FDIGITS+SF_IDIGITS)/sizeof(int) + 1)*sizeof(int))
+
+/* tables for numerical translation */
+#define _Sfpos10 (_Sftable.sf_pos10)
+#define _Sfneg10 (_Sftable.sf_neg10)
+#define _Sfdec (_Sftable.sf_dec)
+#define _Sfdigits (_Sftable.sf_digits)
+#define _Sfcvinitf (_Sftable.sf_cvinitf)
+#define _Sfcvinit (_Sftable.sf_cvinit)
+#define _Sffmtposf (_Sftable.sf_fmtposf)
+#define _Sffmtintf (_Sftable.sf_fmtintf)
+#define _Sfcv36 (_Sftable.sf_cv36)
+#define _Sfcv64 (_Sftable.sf_cv64)
+#define _Sftype (_Sftable.sf_type)
+#define _Sfieee (&_Sftable.sf_ieee)
+#define _Sffinf (_Sftable.sf_ieee.fltinf)
+#define _Sfdinf (_Sftable.sf_ieee.dblinf)
+#define _Sflinf (_Sftable.sf_ieee.ldblinf)
+#define _Sffnan (_Sftable.sf_ieee.fltnan)
+#define _Sfdnan (_Sftable.sf_ieee.dblnan)
+#define _Sflnan (_Sftable.sf_ieee.ldblnan)
+#define _Sffpow10 (_Sftable.sf_flt_pow10)
+#define _Sfdpow10 (_Sftable.sf_dbl_pow10)
+#define _Sflpow10 (_Sftable.sf_ldbl_pow10)
+typedef struct _sfieee_s Sfieee_t;
+struct _sfieee_s
+{ float fltnan; /* float NAN */
+ float fltinf; /* float INF */
+ double dblnan; /* double NAN */
+ double dblinf; /* double INF */
+ Sfdouble_t ldblnan; /* Sfdouble_t NAN */
+ Sfdouble_t ldblinf; /* Sfdouble_t INF */
+};
+typedef struct _sftab_
+{ Sfdouble_t sf_pos10[SF_MAXEXP10]; /* positive powers of 10 */
+ Sfdouble_t sf_neg10[SF_MAXEXP10]; /* negative powers of 10 */
+ uchar sf_dec[200]; /* ascii reps of values < 100 */
+ char* sf_digits; /* digits for general bases */
+ int (*sf_cvinitf)(); /* initialization function */
+ int sf_cvinit; /* initialization state */
+ Fmtpos_t* (*sf_fmtposf)_ARG_((Sfio_t*,const char*,va_list,Sffmt_t*,int));
+ char* (*sf_fmtintf)_ARG_((const char*,int*));
+ float* sf_flt_pow10; /* float powers of 10 */
+ double* sf_dbl_pow10; /* double powers of 10 */
+ Sfdouble_t* sf_ldbl_pow10; /* Sfdouble_t powers of 10 */
+ uchar sf_cv36[SF_MAXCHAR+1]; /* conversion for base [2-36] */
+ uchar sf_cv64[SF_MAXCHAR+1]; /* conversion for base [37-64] */
+ uchar sf_type[SF_MAXCHAR+1]; /* conversion formats&types */
+ Sfieee_t sf_ieee; /* IEEE floating point constants*/
+} Sftab_t;
+
+/* thread-safe macro/function to initialize _Sfcv* conversion tables */
+#define SFCVINIT() (_Sfcvinit ? 1 : (_Sfcvinit = (*_Sfcvinitf)()) )
+
+/* sfucvt() converts decimal integers to ASCII */
+#define SFDIGIT(v,scale,digit) \
+ { if(v < 5*scale) \
+ if(v < 2*scale) \
+ if(v < 1*scale) \
+ { digit = '0'; } \
+ else { digit = '1'; v -= 1*scale; } \
+ else if(v < 3*scale) \
+ { digit = '2'; v -= 2*scale; } \
+ else if(v < 4*scale) \
+ { digit = '3'; v -= 3*scale; } \
+ else { digit = '4'; v -= 4*scale; } \
+ else if(v < 7*scale) \
+ if(v < 6*scale) \
+ { digit = '5'; v -= 5*scale; } \
+ else { digit = '6'; v -= 6*scale; } \
+ else if(v < 8*scale) \
+ { digit = '7'; v -= 7*scale; } \
+ else if(v < 9*scale) \
+ { digit = '8'; v -= 8*scale; } \
+ else { digit = '9'; v -= 9*scale; } \
+ }
+#define sfucvt(v,s,n,list,type,utype) \
+ { while((utype)v >= 10000) \
+ { n = v; v = (type)(((utype)v)/10000); \
+ n = (type)((utype)n - ((utype)v)*10000); \
+ s -= 4; SFDIGIT(n,1000,s[0]); SFDIGIT(n,100,s[1]); \
+ s[2] = *(list = (char*)_Sfdec + (n <<= 1)); s[3] = *(list+1); \
+ } \
+ if(v < 100) \
+ { if(v < 10) \
+ { s -= 1; s[0] = (char)('0'+v); \
+ } else \
+ { s -= 2; s[0] = *(list = (char*)_Sfdec + (v <<= 1)); s[1] = *(list+1); \
+ } \
+ } else \
+ { if(v < 1000) \
+ { s -= 3; SFDIGIT(v,100,s[0]); \
+ s[1] = *(list = (char*)_Sfdec + (v <<= 1)); s[2] = *(list+1); \
+ } else \
+ { s -= 4; SFDIGIT(v,1000,s[0]); SFDIGIT(v,100,s[1]); \
+ s[2] = *(list = (char*)_Sfdec + (v <<= 1)); s[3] = *(list+1); \
+ } \
+ } \
+ }
+
+/* handy functions */
+#undef min
+#undef max
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#define max(x,y) ((x) > (y) ? (x) : (y))
+
+/* fast functions for memory copy and memory clear */
+#if _PACKAGE_ast
+#define memclear(s,n) memzero(s,n)
+#else
+#if _lib_bcopy && !_lib_memcpy
+#define memcpy(to,fr,n) bcopy((fr),(to),(n))
+#endif
+#if _lib_bzero && !_lib_memset
+#define memclear(s,n) bzero((s),(n))
+#else
+#define memclear(s,n) memset((s),'\0',(n))
+#endif
+#endif /*_PACKAGE_ast*/
+
+/* note that MEMCPY advances the associated pointers */
+#define MEMCPY(to,fr,n) \
+ switch(n) \
+ { default : memcpy((Void_t*)to,(Void_t*)fr,n); to += n; fr += n; break; \
+ case 7 : *to++ = *fr++; \
+ case 6 : *to++ = *fr++; \
+ case 5 : *to++ = *fr++; \
+ case 4 : *to++ = *fr++; \
+ case 3 : *to++ = *fr++; \
+ case 2 : *to++ = *fr++; \
+ case 1 : *to++ = *fr++; \
+ }
+#define MEMSET(s,c,n) \
+ switch(n) \
+ { default : memset((Void_t*)s,(int)c,n); s += n; break; \
+ case 7 : *s++ = c; \
+ case 6 : *s++ = c; \
+ case 5 : *s++ = c; \
+ case 4 : *s++ = c; \
+ case 3 : *s++ = c; \
+ case 2 : *s++ = c; \
+ case 1 : *s++ = c; \
+ }
+
+_BEGIN_EXTERNS_
+
+extern Sftab_t _Sftable;
+
+extern int _sfpopen _ARG_((Sfio_t*, int, int, int));
+extern int _sfpclose _ARG_((Sfio_t*));
+extern int _sfexcept _ARG_((Sfio_t*, int, ssize_t, Sfdisc_t*));
+extern Sfrsrv_t* _sfrsrv _ARG_((Sfio_t*, ssize_t));
+extern int _sfsetpool _ARG_((Sfio_t*));
+extern char* _sfcvt _ARG_((Void_t*,char*,size_t,int,int*,int*,int*,int));
+extern char** _sfgetpath _ARG_((char*));
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+#if !_BLD_sfio && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Sfextern_t _Sfextern;
+
+extern int _sfmode _ARG_((Sfio_t*, int, int));
+extern int _sftype _ARG_((const char*, int*, int*));
+
+#undef extern
+
+#ifndef errno
+extern int errno;
+#endif
+
+/* for portable encoding of double values */
+#ifndef frexpl
+#if _ast_fltmax_double
+#define frexpl frexp
+#endif
+#if !__STDC__
+extern Sfdouble_t frexpl _ARG_((Sfdouble_t, int*));
+#endif
+#endif
+#ifndef ldexpl
+#if _ast_fltmax_double
+#define ldexpl ldexp
+#endif
+#if !__STDC__
+extern Sfdouble_t ldexpl _ARG_((Sfdouble_t, int));
+#endif
+#endif
+
+#if !_PACKAGE_ast
+
+#if !__STDC__ && !_hdr_stdlib
+extern void abort _ARG_((void));
+extern int atexit _ARG_((void(*)(void)));
+extern char* getenv _ARG_((const char*));
+extern void* malloc _ARG_((size_t));
+extern void* realloc _ARG_((void*, size_t));
+extern void free _ARG_((void*));
+extern size_t strlen _ARG_((const char*));
+extern char* strcpy _ARG_((char*, const char*));
+
+extern Void_t* memset _ARG_((void*, int, size_t));
+extern Void_t* memchr _ARG_((const void*, int, size_t));
+extern Void_t* memccpy _ARG_((void*, const void*, int, size_t));
+#ifndef memcpy
+extern Void_t* memcpy _ARG_((void*, const void*, size_t));
+#endif
+#if !defined(strtod)
+extern double strtod _ARG_((const char*, char**));
+#endif
+#if !defined(remove)
+extern int sysremovef _ARG_((const char*));
+#endif
+#endif /* !__STDC__ && !_hdr_stdlib */
+
+#if !_hdr_unistd
+#if _proto_open && __cplusplus
+extern int sysopenf _ARG_((const char*, int, ...));
+#endif
+extern int sysclosef _ARG_((int));
+extern ssize_t sysreadf _ARG_((int, void*, size_t));
+extern ssize_t syswritef _ARG_((int, const void*, size_t));
+extern sfoff_t syslseekf _ARG_((int, sfoff_t, int));
+extern int sysdupf _ARG_((int));
+extern int syspipef _ARG_((int*));
+extern int sysaccessf _ARG_((const char*, int));
+extern int sysremovef _ARG_((const char*));
+extern int sysfstatf _ARG_((int, sfstat_t*));
+extern int sysstatf _ARG_((const char*, sfstat_t*));
+
+extern int isatty _ARG_((int));
+
+extern int wait _ARG_((int*));
+extern uint sleep _ARG_((uint));
+extern int execl _ARG_((const char*, const char*,...));
+extern int execv _ARG_((const char*, char**));
+#if !defined(fork)
+extern int fork _ARG_((void));
+#endif
+#if _lib_unlink
+extern int unlink _ARG_((const char*));
+#endif
+
+#endif /*_hdr_unistd*/
+
+#if _lib_bcopy && !_proto_bcopy
+extern void bcopy _ARG_((const void*, void*, size_t));
+#endif
+#if _lib_bzero && !_proto_bzero
+extern void bzero _ARG_((void*, size_t));
+#endif
+
+extern time_t time _ARG_((time_t*));
+extern int waitpid _ARG_((int,int*,int));
+extern void _exit _ARG_((int));
+typedef int(* Onexit_f)_ARG_((void));
+extern Onexit_f onexit _ARG_((Onexit_f));
+
+#if _lib_vfork && !_hdr_vfork && !_sys_vfork
+extern pid_t vfork _ARG_((void));
+#endif /*_lib_vfork*/
+
+#if _lib_poll
+#if _lib_poll_fd_1
+extern int poll _ARG_((struct pollfd*, ulong, int));
+#else
+extern int poll _ARG_((ulong, struct pollfd*, int));
+#endif
+#endif /*_lib_poll*/
+
+#endif /* _PACKAGE_ast */
+
+_END_EXTERNS_
+
+#endif /*_SFHDR_H*/
diff --git a/src/lib/libast/sfio/sfllen.c b/src/lib/libast/sfio/sfllen.c
new file mode 100644
index 0000000..4dd4879
--- /dev/null
+++ b/src/lib/libast/sfio/sfllen.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Get size of a long value coded in a portable format
+**
+** Written by Kiem-Phong Vo
+*/
+#if __STD_C
+int _sfllen(Sflong_t v)
+#else
+int _sfllen(v)
+Sflong_t v;
+#endif
+{
+ if(v < 0)
+ v = -(v+1);
+ v = (Sfulong_t)v >> SF_SBITS;
+ return 1 + (v > 0 ? sfulen(v) : 0);
+}
diff --git a/src/lib/libast/sfio/sfmode.c b/src/lib/libast/sfio/sfmode.c
new file mode 100644
index 0000000..97182fb
--- /dev/null
+++ b/src/lib/libast/sfio/sfmode.c
@@ -0,0 +1,596 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+static char* Version = "\n@(#)$Id: sfio (AT&T Labs - Research) 2009-09-15 $\0\n";
+
+/* Functions to set a given stream to some desired mode
+**
+** Written by Kiem-Phong Vo.
+**
+** Modifications:
+** 06/27/1990 (first version)
+** 01/06/1991
+** 07/08/1991
+** 06/18/1992
+** 02/02/1993
+** 05/25/1993
+** 02/07/1994
+** 05/21/1996
+** 08/01/1997
+** 08/01/1998 (extended formatting)
+** 09/09/1999 (thread-safe)
+** 02/01/2001 (adaptive buffering)
+** 05/31/2002 (multi-byte handling in sfvprintf/vscanf)
+** 09/06/2002 (SF_IOINTR flag)
+** 11/15/2002 (%#c for sfvprintf)
+** 05/31/2003 (sfsetbuf(f,f,align_size) to set alignment for data)
+** (%I1d is fixed to handle "signed char" correctly)
+** 01/01/2004 Porting issues to various platforms resolved.
+** 06/01/2008 Allowing notify() at entering/exiting thread-safe routines.
+** 09/15/2008 Add sfwalk().
+*/
+
+/* the below is for protecting the application from SIGPIPE */
+#if _PACKAGE_ast
+#include <sig.h>
+#include <wait.h>
+#define Sfsignal_f Sig_handler_t
+#else
+#include <signal.h>
+typedef void(* Sfsignal_f)_ARG_((int));
+#endif
+static int _Sfsigp = 0; /* # of streams needing SIGPIPE protection */
+
+/* done at exiting time */
+#if __STD_C
+static void _sfcleanup(void)
+#else
+static void _sfcleanup()
+#endif
+{
+ reg Sfpool_t* p;
+ reg Sfio_t* f;
+ reg int n;
+ reg int pool;
+
+ f = (Sfio_t*)Version; /* shut compiler warning */
+
+ /* set this so that no more buffering is allowed for write streams */
+ _Sfexiting = 1001;
+
+ sfsync(NIL(Sfio_t*));
+
+ for(p = &_Sfpool; p; p = p->next)
+ { for(n = 0; n < p->n_sf; ++n)
+ { if(!(f = p->sf[n]) || SFFROZEN(f) )
+ continue;
+
+ SFLOCK(f,0);
+ SFMTXLOCK(f);
+
+ /* let application know that we are leaving */
+ (void)SFRAISE(f, SF_ATEXIT, NIL(Void_t*));
+
+ if(f->flags&SF_STRING)
+ continue;
+
+ /* from now on, write streams are unbuffered */
+ pool = f->mode&SF_POOL;
+ f->mode &= ~SF_POOL;
+ if((f->flags&SF_WRITE) && !(f->mode&SF_WRITE))
+ (void)_sfmode(f,SF_WRITE,1);
+ if(f->data &&
+ ((f->bits&SF_MMAP) ||
+ ((f->mode&SF_WRITE) && f->next == f->data) ) )
+ (void)SFSETBUF(f,NIL(Void_t*),0);
+ f->mode |= pool;
+
+ SFMTXUNLOCK(f);
+ SFOPEN(f,0);
+ }
+ }
+}
+
+/* put into discrete pool */
+#if __STD_C
+int _sfsetpool(Sfio_t* f)
+#else
+int _sfsetpool(f)
+Sfio_t* f;
+#endif
+{
+ reg Sfpool_t* p;
+ reg Sfio_t** array;
+ reg int n, rv;
+
+ if(!_Sfcleanup)
+ { _Sfcleanup = _sfcleanup;
+ (void)atexit(_sfcleanup);
+ }
+
+ if(!(p = f->pool) )
+ p = f->pool = &_Sfpool;
+
+ POOLMTXENTER(p);
+
+ rv = -1;
+
+ if(p->n_sf >= p->s_sf)
+ { if(p->s_sf == 0) /* initialize pool array */
+ { p->s_sf = sizeof(p->array)/sizeof(p->array[0]);
+ p->sf = p->array;
+ }
+ else /* allocate a larger array */
+ { n = (p->sf != p->array ? p->s_sf : (p->s_sf/4 + 1)*4) + 4;
+ if(!(array = (Sfio_t**)malloc(n*sizeof(Sfio_t*))) )
+ goto done;
+
+ /* move old array to new one */
+ memcpy((Void_t*)array,(Void_t*)p->sf,p->n_sf*sizeof(Sfio_t*));
+ if(p->sf != p->array)
+ free((Void_t*)p->sf);
+
+ p->sf = array;
+ p->s_sf = n;
+ }
+ }
+
+ /* always add at end of array because if this was done during some sort
+ of walk thru all streams, we'll want the new stream to be seen.
+ */
+ p->sf[p->n_sf++] = f;
+ rv = 0;
+
+done:
+ POOLMTXRETURN(p, rv);
+}
+
+/* create an auxiliary buffer for sfgetr/sfreserve/sfputr */
+#if __STD_C
+Sfrsrv_t* _sfrsrv(reg Sfio_t* f, reg ssize_t size)
+#else
+Sfrsrv_t* _sfrsrv(f,size)
+reg Sfio_t* f;
+reg ssize_t size;
+#endif
+{
+ Sfrsrv_t *rsrv, *rs;
+
+ /* make buffer if nothing yet */
+ size = ((size + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
+ if(!(rsrv = f->rsrv) || size > rsrv->size)
+ { if(!(rs = (Sfrsrv_t*)malloc(size+sizeof(Sfrsrv_t))))
+ size = -1;
+ else
+ { if(rsrv)
+ { if(rsrv->slen > 0)
+ memcpy(rs,rsrv,sizeof(Sfrsrv_t)+rsrv->slen);
+ free(rsrv);
+ }
+ f->rsrv = rsrv = rs;
+ rsrv->size = size;
+ rsrv->slen = 0;
+ }
+ }
+
+ if(rsrv && size > 0)
+ rsrv->slen = 0;
+
+ return size >= 0 ? rsrv : NIL(Sfrsrv_t*);
+}
+
+#ifdef SIGPIPE
+#if __STD_C
+static void ignoresig(int sig)
+#else
+static void ignoresig(sig)
+int sig;
+#endif
+{
+ signal(sig, ignoresig);
+}
+#endif
+
+#if __STD_C
+int _sfpopen(reg Sfio_t* f, int fd, int pid, int stdio)
+#else
+int _sfpopen(f, fd, pid, stdio)
+reg Sfio_t* f;
+int fd;
+int pid;
+int stdio; /* stdio popen() does not reset SIGPIPE handler */
+#endif
+{
+ reg Sfproc_t* p;
+
+ if(f->proc)
+ return 0;
+
+ if(!(p = f->proc = (Sfproc_t*)malloc(sizeof(Sfproc_t))) )
+ return -1;
+
+ p->pid = pid;
+ p->size = p->ndata = 0;
+ p->rdata = NIL(uchar*);
+ p->file = fd;
+ p->sigp = (!stdio && pid >= 0 && (f->flags&SF_WRITE)) ? 1 : 0;
+
+#ifdef SIGPIPE /* protect from broken pipe signal */
+ if(p->sigp)
+ { Sfsignal_f handler;
+
+ (void)vtmtxlock(_Sfmutex);
+ if((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL &&
+ handler != ignoresig)
+ signal(SIGPIPE, handler); /* honor user handler */
+ _Sfsigp += 1;
+ (void)vtmtxunlock(_Sfmutex);
+ }
+#endif
+
+ return 0;
+}
+
+#if __STD_C
+int _sfpclose(reg Sfio_t* f)
+#else
+int _sfpclose(f)
+reg Sfio_t* f; /* stream to close */
+#endif
+{
+ Sfproc_t* p;
+ int pid, status;
+
+ if(!(p = f->proc))
+ return -1;
+ f->proc = NIL(Sfproc_t*);
+
+ if(p->rdata)
+ free(p->rdata);
+
+ if(p->pid < 0)
+ status = 0;
+ else
+ { /* close the associated stream */
+ if(p->file >= 0)
+ CLOSE(p->file);
+
+ /* wait for process termination */
+#if _PACKAGE_ast
+ sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
+#endif
+ while ((pid = waitpid(p->pid,&status,0)) == -1 && errno == EINTR)
+ ;
+ if(pid == -1)
+ status = -1;
+#if _PACKAGE_ast
+ sigcritical(0);
+#endif
+
+#ifdef SIGPIPE
+ (void)vtmtxlock(_Sfmutex);
+ if(p->sigp && (_Sfsigp -= 1) <= 0)
+ { Sfsignal_f handler;
+ if((handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL &&
+ handler != ignoresig)
+ signal(SIGPIPE,handler); /* honor user handler */
+ _Sfsigp = 0;
+ }
+ (void)vtmtxunlock(_Sfmutex);
+#endif
+ }
+
+ free(p);
+ return status;
+}
+
+#if __STD_C
+static int _sfpmode(Sfio_t* f, int type)
+#else
+static int _sfpmode(f,type)
+Sfio_t* f;
+int type;
+#endif
+{
+ Sfproc_t* p;
+
+ if(!(p = f->proc) )
+ return -1;
+
+ if(type == SF_WRITE)
+ { /* save unread data */
+ p->ndata = f->endb-f->next;
+ if(p->ndata > p->size)
+ { if(p->rdata)
+ free((char*)p->rdata);
+ if((p->rdata = (uchar*)malloc(p->ndata)) )
+ p->size = p->ndata;
+ else
+ { p->size = 0;
+ return -1;
+ }
+ }
+ if(p->ndata > 0)
+ memcpy((Void_t*)p->rdata,(Void_t*)f->next,p->ndata);
+ f->endb = f->data;
+ }
+ else
+ { /* restore read data */
+ if(p->ndata > f->size) /* may lose data!!! */
+ p->ndata = f->size;
+ if(p->ndata > 0)
+ { memcpy((Void_t*)f->data,(Void_t*)p->rdata,p->ndata);
+ f->endb = f->data+p->ndata;
+ p->ndata = 0;
+ }
+ }
+
+ /* switch file descriptor */
+ if(p->pid >= 0)
+ { type = f->file;
+ f->file = p->file;
+ p->file = type;
+ }
+
+ return 0;
+}
+
+#if __STD_C
+int _sfmode(reg Sfio_t* f, reg int wanted, reg int local)
+#else
+int _sfmode(f, wanted, local)
+reg Sfio_t* f; /* change r/w mode and sync file pointer for this stream */
+reg int wanted; /* desired mode */
+reg int local; /* a local call */
+#endif
+{
+ reg int n;
+ Sfoff_t addr;
+ reg int rv = 0;
+
+ SFONCE(); /* initialize mutexes */
+
+ if(wanted&SF_SYNCED) /* for (SF_SYNCED|SF_READ) stream, just junk data */
+ { wanted &= ~SF_SYNCED;
+ if((f->mode&(SF_SYNCED|SF_READ)) == (SF_SYNCED|SF_READ) )
+ { f->next = f->endb = f->endr = f->data;
+ f->mode &= ~SF_SYNCED;
+ }
+ }
+
+ if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0))
+ { if(local || !f->disc || !f->disc->exceptf)
+ { local = 1;
+ goto err_notify;
+ }
+
+ for(;;)
+ { if((rv = (*f->disc->exceptf)(f,SF_LOCKED,0,f->disc)) < 0)
+ return rv;
+ if((!local && SFFROZEN(f)) ||
+ (!(f->flags&SF_STRING) && f->file < 0) )
+ { if(rv == 0)
+ { local = 1;
+ goto err_notify;
+ }
+ else continue;
+ }
+ else break;
+ }
+ }
+
+ if(f->mode&SF_GETR)
+ { f->mode &= ~SF_GETR;
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && (f->tiny[0] += 1) >= (4*SF_NMAP) )
+ { /* turn off mmap to avoid page faulting */
+ sfsetbuf(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+ f->tiny[0] = 0;
+ }
+ else
+#endif
+ if(f->getr)
+ { f->next[-1] = f->getr;
+ f->getr = 0;
+ }
+ }
+
+ if(f->mode&SF_STDIO) /* synchronizing with stdio pointers */
+ (*_Sfstdsync)(f);
+
+ if(f->disc == _Sfudisc && wanted == SF_WRITE &&
+ sfclose((*_Sfstack)(f,NIL(Sfio_t*))) < 0 )
+ { local = 1;
+ goto err_notify;
+ }
+
+ if(f->mode&SF_POOL)
+ { /* move to head of pool */
+ if(f == f->pool->sf[0] || (*_Sfpmove)(f,0) < 0 )
+ { local = 1;
+ goto err_notify;
+ }
+ f->mode &= ~SF_POOL;
+ }
+
+ SFLOCK(f,local);
+
+ /* buffer initialization */
+ wanted &= SF_RDWR;
+ if(f->mode&SF_INIT)
+ {
+ if(!f->pool && _sfsetpool(f) < 0)
+ { rv = -1;
+ goto done;
+ }
+
+ if(wanted == 0)
+ goto done;
+
+ if(wanted != (int)(f->mode&SF_RDWR) && !(f->flags&wanted) )
+ goto err_notify;
+
+ if((f->flags&SF_STRING) && f->size >= 0 && f->data)
+ { f->mode &= ~SF_INIT;
+ f->extent = ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ?
+ f->size : 0;
+ f->here = 0;
+ f->endb = f->data + f->size;
+ f->next = f->endr = f->endw = f->data;
+ if(f->mode&SF_READ)
+ f->endr = f->endb;
+ else f->endw = f->endb;
+ }
+ else
+ { n = f->flags;
+ (void)SFSETBUF(f,f->data,f->size);
+ f->flags |= (n&SF_MALLOC);
+ }
+ }
+
+ if(wanted == (int)SFMODE(f,1))
+ goto done;
+
+ switch(SFMODE(f,1))
+ {
+ case SF_WRITE: /* switching to SF_READ */
+ if(wanted == 0 || wanted == SF_WRITE)
+ break;
+ if(!(f->flags&SF_READ) )
+ goto err_notify;
+ else if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+ f->endb = f->data+f->extent;
+ f->mode = SF_READ;
+ break;
+ }
+
+ /* reset buffer */
+ if(f->next > f->data && SFFLSBUF(f,-1) < 0)
+ goto err_notify;
+
+ if(f->size == 0)
+ { /* unbuffered */
+ f->data = f->tiny;
+ f->size = sizeof(f->tiny);
+ }
+ f->next = f->endr = f->endw = f->endb = f->data;
+ f->mode = SF_READ|SF_LOCK;
+
+ /* restore saved read data for coprocess */
+ if(f->proc && _sfpmode(f,wanted) < 0)
+ goto err_notify;
+
+ break;
+
+ case (SF_READ|SF_SYNCED): /* a previously sync-ed read stream */
+ if(wanted != SF_WRITE)
+ { /* just reset the pointers */
+ f->mode = SF_READ|SF_LOCK;
+
+ /* see if must go with new physical location */
+ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) &&
+ (addr = SFSK(f,0,SEEK_CUR,f->disc)) != f->here)
+ {
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->endb = f->endr = f->endw = f->next = f->data;
+ f->here = addr;
+ }
+ else
+ { addr = f->here + (f->endb - f->next);
+ if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
+ goto err_notify;
+ f->here = addr;
+ }
+
+ break;
+ }
+ /* fall thru */
+
+ case SF_READ: /* switching to SF_WRITE */
+ if(wanted != SF_WRITE)
+ break;
+ else if(!(f->flags&SF_WRITE))
+ goto err_notify;
+ else if(f->flags&SF_STRING)
+ { f->endb = f->data+f->size;
+ f->mode = SF_WRITE|SF_LOCK;
+ break;
+ }
+
+ /* save unread data before switching mode */
+ if(f->proc && _sfpmode(f,wanted) < 0)
+ goto err_notify;
+
+ /* reset buffer and seek pointer */
+ if(!(f->mode&SF_SYNCED) )
+ { n = f->endb - f->next;
+ if(f->extent >= 0 && (n > 0 || (f->data && (f->bits&SF_MMAP))) )
+ { /* reset file pointer */
+ addr = f->here - n;
+ if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
+ goto err_notify;
+ f->here = addr;
+ }
+ }
+
+ f->mode = SF_WRITE|SF_LOCK;
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { if(f->data)
+ SFMUNMAP(f,f->data,f->endb-f->data);
+ (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+ }
+#endif
+ if(f->data == f->tiny)
+ { f->endb = f->data = f->next = NIL(uchar*);
+ f->size = 0;
+ }
+ else f->endb = (f->next = f->data) + f->size;
+
+ break;
+
+ default: /* unknown case */
+ err_notify:
+ if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR)
+ wanted = SF_READ;
+
+ /* set errno for operations that access wrong stream type */
+ if(wanted != (f->mode&SF_RDWR) && f->file >= 0)
+ errno = EBADF;
+
+ if(_Sfnotify) /* notify application of the error */
+ (*_Sfnotify)(f, wanted, (void*)((long)f->file));
+
+ rv = -1;
+ break;
+ }
+
+done:
+ SFOPEN(f,local);
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfmove.c b/src/lib/libast/sfio/sfmove.c
new file mode 100644
index 0000000..9e39657
--- /dev/null
+++ b/src/lib/libast/sfio/sfmove.c
@@ -0,0 +1,242 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Move data from one stream to another.
+** This code is written so that it'll work even in the presence
+** of stacking streams, pool, and discipline.
+** If you must change it, be gentle.
+**
+** Written by Kiem-Phong Vo.
+*/
+#define MAX_SSIZE ((ssize_t)((~((size_t)0)) >> 1))
+
+#if __STD_C
+Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, reg int rc)
+#else
+Sfoff_t sfmove(fr,fw,n,rc)
+Sfio_t* fr; /* moving data from this stream */
+Sfio_t* fw; /* moving data to this stream */
+Sfoff_t n; /* number of bytes/records to move. <0 for unbounded move */
+reg int rc; /* record separator */
+#endif
+{
+ reg uchar *cp, *next;
+ reg ssize_t r, w;
+ reg uchar *endb;
+ reg int direct;
+ Sfoff_t n_move, sk, cur;
+ uchar *rbuf = NIL(uchar*);
+ ssize_t rsize = 0;
+ SFMTXDECL(fr); /* declare a shadow stream variable for from stream */
+ SFMTXDECL2(fw); /* declare a shadow stream variable for to stream */
+
+ SFMTXENTER(fr, (Sfoff_t)0);
+ if(fw)
+ SFMTXBEGIN2(fw, (Sfoff_t)0);
+
+ for(n_move = 0; n != 0; )
+ {
+ if(rc >= 0) /* moving records, let sfgetr() deal with record reading */
+ { if(!(cp = (uchar*)sfgetr(fr,rc,0)) )
+ n = 0;
+ else
+ { r = sfvalue(fr);
+ if(fw && (w = SFWRITE(fw, cp, r)) != r)
+ { if(fr->extent >= 0 )
+ (void)SFSEEK(fr,(Sfoff_t)(-r),SEEK_CUR);
+ if(fw->extent >= 0 && w > 0)
+ (void)SFSEEK(fw,(Sfoff_t)(-w),SEEK_CUR);
+ n = 0;
+ }
+ else
+ { n_move += 1;
+ if(n > 0)
+ n -= 1;
+ }
+ }
+ continue;
+ }
+
+ /* get the streams into the right mode */
+ if(fr->mode != SF_READ && _sfmode(fr,SF_READ,0) < 0)
+ break;
+
+ SFLOCK(fr,0);
+
+ /* flush the write buffer as necessary to make room */
+ if(fw)
+ { if(fw->mode != SF_WRITE && _sfmode(fw,SF_WRITE,0) < 0 )
+ break;
+ SFLOCK(fw,0);
+ if(fw->next >= fw->endb ||
+ (fw->next > fw->data && fr->extent < 0 &&
+ (fw->extent < 0 || (fw->flags&SF_SHARE)) ) )
+ if(SFFLSBUF(fw,-1) < 0 )
+ break;
+ }
+ else if((cur = SFSEEK(fr, (Sfoff_t)0, SEEK_CUR)) >= 0 )
+ { sk = n > 0 ? SFSEEK(fr, n, SEEK_CUR) : SFSEEK(fr, 0, SEEK_END);
+ if(sk > cur) /* safe to skip over data in current stream */
+ { n_move += sk - cur;
+ if(n > 0)
+ n -= sk - cur;
+ continue;
+ }
+ /* else: stream unstacking may happen below */
+ }
+
+ /* about to move all, set map to a large amount */
+ if(n < 0 && (fr->bits&SF_MMAP) && !(fr->bits&SF_MVSIZE) )
+ { SFMVSET(fr);
+ fr->bits |= SF_SEQUENTIAL; /* sequentially access data */
+ }
+
+ /* try reading a block of data */
+ direct = 0;
+ if((r = fr->endb - (next = fr->next)) <= 0)
+ { /* amount of data remained to be read */
+ if((w = n > MAX_SSIZE ? MAX_SSIZE : (ssize_t)n) < 0)
+ { if(fr->extent < 0)
+ w = fr->data == fr->tiny ? SF_GRAIN : fr->size;
+ else if((fr->extent-fr->here) > SF_NMAP*SF_PAGE)
+ w = SF_NMAP*SF_PAGE;
+ else w = (ssize_t)(fr->extent-fr->here);
+ }
+
+ /* use a decent buffer for data transfer but make sure
+ that if we overread, the left over can be retrieved
+ */
+ if(!(fr->flags&SF_STRING) && !(fr->bits&SF_MMAP) &&
+ (n < 0 || fr->extent >= 0) )
+ { reg ssize_t maxw = 4*(_Sfpage > 0 ? _Sfpage : SF_PAGE);
+
+ /* direct transfer to a seekable write stream */
+ if(fw && fw->extent >= 0 && w <= (fw->endb-fw->next) )
+ { w = fw->endb - (next = fw->next);
+ direct = SF_WRITE;
+ }
+ else if(w > fr->size && maxw > fr->size)
+ { /* making our own buffer */
+ if(w >= maxw)
+ w = maxw;
+ else w = ((w+fr->size-1)/fr->size)*fr->size;
+ if(rsize <= 0 && (rbuf = (uchar*)malloc(w)) )
+ rsize = w;
+ if(rbuf)
+ { next = rbuf;
+ w = rsize;
+ direct = SF_STRING;
+ }
+ }
+ }
+
+ if(!direct)
+ { /* make sure we don't read too far ahead */
+ if(n > 0 && fr->extent < 0 && (fr->flags&SF_SHARE) )
+ { if((Sfoff_t)(r = fr->size) > n)
+ r = (ssize_t)n;
+ }
+ else r = -1;
+ if((r = SFFILBUF(fr,r)) <= 0)
+ break;
+ next = fr->next;
+ }
+ else
+ { /* actual amount to be read */
+ if(n > 0 && n < w)
+ w = (ssize_t)n;
+
+ if((r = SFRD(fr,next,w,fr->disc)) > 0)
+ fr->next = fr->endb = fr->endr = fr->data;
+ else if(r == 0)
+ break; /* eof */
+ else goto again; /* popped stack */
+ }
+ }
+
+ /* compute the extent of data to be moved */
+ endb = next+r;
+ if(n > 0)
+ { if(r > n)
+ r = (ssize_t)n;
+ n -= r;
+ }
+ n_move += r;
+ cp = next+r;
+
+ if(!direct)
+ fr->next += r;
+ else if((w = endb-cp) > 0)
+ { /* move left-over to read stream */
+ if(w > fr->size)
+ w = fr->size;
+ memcpy((Void_t*)fr->data,(Void_t*)cp,w);
+ fr->endb = fr->data+w;
+ if((w = endb - (cp+w)) > 0)
+ (void)SFSK(fr,(Sfoff_t)(-w),SEEK_CUR,fr->disc);
+ }
+
+ if(fw)
+ { if(direct == SF_WRITE)
+ fw->next += r;
+ else if(r <= (fw->endb-fw->next) )
+ { memcpy((Void_t*)fw->next,(Void_t*)next,r);
+ fw->next += r;
+ }
+ else if((w = SFWRITE(fw,(Void_t*)next,r)) != r)
+ { /* a write error happened */
+ if(w > 0)
+ { r -= w;
+ n_move -= r;
+ }
+ if(fr->extent >= 0)
+ (void)SFSEEK(fr,(Sfoff_t)(-r),SEEK_CUR);
+ break;
+ }
+ }
+
+ again:
+ SFOPEN(fr,0);
+ if(fw)
+ SFOPEN(fw,0);
+ }
+
+ if(n < 0 && (fr->bits&SF_MMAP) && (fr->bits&SF_MVSIZE))
+ { /* back to normal access mode */
+ SFMVUNSET(fr);
+ if((fr->bits&SF_SEQUENTIAL) && (fr->data))
+ SFMMSEQOFF(fr,fr->data,fr->endb-fr->data);
+ fr->bits &= ~SF_SEQUENTIAL;
+ }
+
+ if(rbuf)
+ free(rbuf);
+
+ if(fw)
+ { SFOPEN(fw,0);
+ SFMTXEND2(fw);
+ }
+
+ SFOPEN(fr,0);
+ SFMTXRETURN(fr, n_move);
+}
diff --git a/src/lib/libast/sfio/sfmutex.c b/src/lib/libast/sfio/sfmutex.c
new file mode 100644
index 0000000..cc3a4b7
--- /dev/null
+++ b/src/lib/libast/sfio/sfmutex.c
@@ -0,0 +1,69 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Obtain/release exclusive use of a stream.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* the main locking/unlocking interface */
+#if __STD_C
+int sfmutex(Sfio_t* f, int type)
+#else
+int sfmutex(f, type)
+Sfio_t* f;
+int type;
+#endif
+{
+#if !vt_threaded
+ NOTUSED(f); NOTUSED(type);
+ return 0;
+#else
+
+ SFONCE();
+
+ if(!f)
+ return -1;
+
+ if(!f->mutex)
+ { if(f->bits&SF_PRIVATE)
+ return 0;
+
+ vtmtxlock(_Sfmutex);
+ f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT);
+ vtmtxunlock(_Sfmutex);
+ if(!f->mutex)
+ return -1;
+ }
+
+ if(type == SFMTX_LOCK)
+ return vtmtxlock(f->mutex);
+ else if(type == SFMTX_TRYLOCK)
+ return vtmtxtrylock(f->mutex);
+ else if(type == SFMTX_UNLOCK)
+ return vtmtxunlock(f->mutex);
+ else if(type == SFMTX_CLRLOCK)
+ return vtmtxclrlock(f->mutex);
+ else return -1;
+#endif /*vt_threaded*/
+}
diff --git a/src/lib/libast/sfio/sfnew.c b/src/lib/libast/sfio/sfnew.c
new file mode 100644
index 0000000..a6feddc
--- /dev/null
+++ b/src/lib/libast/sfio/sfnew.c
@@ -0,0 +1,129 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Fundamental function to create a new stream.
+** The argument flags defines the type of stream and the scheme
+** of buffering.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Sfio_t* sfnew(Sfio_t* oldf, Void_t* buf, size_t size, int file, int flags)
+#else
+Sfio_t* sfnew(oldf,buf,size,file,flags)
+Sfio_t* oldf; /* old stream to be reused */
+Void_t* buf; /* a buffer to read/write, if NULL, will be allocated */
+size_t size; /* buffer size if buf is given or desired buffer size */
+int file; /* file descriptor to read/write from */
+int flags; /* type of file stream */
+#endif
+{
+ reg Sfio_t* f;
+ reg int sflags;
+
+ SFONCE(); /* initialize mutexes */
+
+ if(!(flags&SF_RDWR))
+ return NIL(Sfio_t*);
+
+ sflags = 0;
+ if((f = oldf) )
+ { if(flags&SF_EOF)
+ { if(f != sfstdin && f != sfstdout && f != sfstderr)
+ f->mutex = NIL(Vtmutex_t*);
+ SFCLEAR(f, f->mutex);
+ oldf = NIL(Sfio_t*);
+ }
+ else if(f->mode&SF_AVAIL)
+ { /* only allow SF_STATIC to be already closed */
+ if(!(f->flags&SF_STATIC) )
+ return NIL(Sfio_t*);
+ sflags = f->flags;
+ oldf = NIL(Sfio_t*);
+ }
+ else
+ { /* reopening an open stream, close it first */
+ sflags = f->flags;
+
+ if(((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) ||
+ SFCLOSE(f) < 0 )
+ return NIL(Sfio_t*);
+
+ if(f->data && ((flags&SF_STRING) || size != (size_t)SF_UNBOUND) )
+ { if(sflags&SF_MALLOC)
+ free((Void_t*)f->data);
+ f->data = NIL(uchar*);
+ }
+ if(!f->data)
+ sflags &= ~SF_MALLOC;
+ }
+ }
+
+ if(!f)
+ { /* reuse a standard stream structure if possible */
+ if(!(flags&SF_STRING) && file >= 0 && file <= 2)
+ { f = file == 0 ? sfstdin : file == 1 ? sfstdout : sfstderr;
+ if(f)
+ { if(f->mode&SF_AVAIL)
+ { sflags = f->flags;
+ SFCLEAR(f, f->mutex);
+ }
+ else f = NIL(Sfio_t*);
+ }
+ }
+
+ if(!f)
+ { if(!(f = (Sfio_t*)malloc(sizeof(Sfio_t))) )
+ return NIL(Sfio_t*);
+ SFCLEAR(f, NIL(Vtmutex_t*));
+ }
+ }
+
+ /* create a mutex */
+ if(!f->mutex)
+ f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT);
+
+ /* stream type */
+ f->mode = (flags&SF_READ) ? SF_READ : SF_WRITE;
+ f->flags = (flags&SF_FLAGS) | (sflags&(SF_MALLOC|SF_STATIC));
+ f->bits = (flags&SF_RDWR) == SF_RDWR ? SF_BOTH : 0;
+ f->file = file;
+ f->here = f->extent = 0;
+ f->getr = f->tiny[0] = 0;
+
+ f->mode |= SF_INIT;
+ if(size != (size_t)SF_UNBOUND)
+ { f->size = size;
+ f->data = size <= 0 ? NIL(uchar*) : (uchar*)buf;
+ }
+ f->endb = f->endr = f->endw = f->next = f->data;
+
+ if(_Sfnotify)
+ (*_Sfnotify)(f, SF_NEW, (void*)((long)f->file));
+
+ if(f->flags&SF_STRING)
+ (void)_sfmode(f,f->mode&SF_RDWR,0);
+
+ return f;
+}
diff --git a/src/lib/libast/sfio/sfnotify.c b/src/lib/libast/sfio/sfnotify.c
new file mode 100644
index 0000000..06cc857
--- /dev/null
+++ b/src/lib/libast/sfio/sfnotify.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+
+/* Set the function to be called when a stream is opened or closed
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+int sfnotify(void(*notify)(Sfio_t*, int, void*))
+#else
+int sfnotify(notify)
+void (*notify)();
+#endif
+{
+ _Sfnotify = notify;
+ return 0;
+}
diff --git a/src/lib/libast/sfio/sfnputc.c b/src/lib/libast/sfio/sfnputc.c
new file mode 100644
index 0000000..58a1430
--- /dev/null
+++ b/src/lib/libast/sfio/sfnputc.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out a character n times
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+ssize_t sfnputc(Sfio_t* f, int c, size_t n)
+#else
+ssize_t sfnputc(f,c,n)
+Sfio_t* f; /* file to write */
+int c; /* char to be written */
+size_t n; /* number of time to repeat */
+#endif
+{
+ reg uchar* ps;
+ reg ssize_t p, w;
+ uchar buf[128];
+ reg int local;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,local);
+
+ /* write into a suitable buffer */
+ if((size_t)(p = (f->endb-(ps = f->next))) < n)
+ { ps = buf; p = sizeof(buf); }
+ if((size_t)p > n)
+ p = n;
+ MEMSET(ps,c,p);
+ ps -= p;
+
+ w = n;
+ if(ps == f->next)
+ { /* simple sfwrite */
+ f->next += p;
+ if(c == '\n')
+ (void)SFFLSBUF(f,-1);
+ goto done;
+ }
+
+ for(;;)
+ { /* hard write of data */
+ if((p = SFWRITE(f,(Void_t*)ps,p)) <= 0 || (n -= p) <= 0)
+ { w -= n;
+ goto done;
+ }
+ if((size_t)p > n)
+ p = n;
+ }
+done :
+ SFOPEN(f,local);
+ SFMTXRETURN(f, w);
+}
diff --git a/src/lib/libast/sfio/sfopen.c b/src/lib/libast/sfio/sfopen.c
new file mode 100644
index 0000000..522bd9e
--- /dev/null
+++ b/src/lib/libast/sfio/sfopen.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/*
+ * _sfopen() wrapper to allow user sfopen() intercept
+ */
+
+extern Sfio_t* _sfopen _ARG_((Sfio_t*, const char*, const char*));
+
+#if __STD_C
+Sfio_t* sfopen(Sfio_t* f, const char* file, const char* mode)
+#else
+Sfio_t* sfopen(f,file,mode)
+Sfio_t* f; /* old stream structure */
+char* file; /* file/string to be opened */
+reg char* mode; /* mode of the stream */
+#endif
+{
+ return _sfopen(f, file, mode);
+}
diff --git a/src/lib/libast/sfio/sfpeek.c b/src/lib/libast/sfio/sfpeek.c
new file mode 100644
index 0000000..22cf807
--- /dev/null
+++ b/src/lib/libast/sfio/sfpeek.c
@@ -0,0 +1,89 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Safe access to the internal stream buffer.
+** This function is obsolete. sfreserve() should be used.
+**
+** Written by Kiem-Phong Vo (06/27/90).
+*/
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if __STD_C
+extern ssize_t sfpeek(reg Sfio_t* f, Void_t** bp, reg size_t size)
+#else
+extern ssize_t sfpeek(f,bp,size)
+reg Sfio_t* f; /* file to peek */
+Void_t** bp; /* start of data area */
+reg size_t size; /* size of peek */
+#endif
+{ reg ssize_t n, sz;
+ reg int mode;
+
+ /* query for the extent of the remainder of the buffer */
+ if((sz = size) == 0 || !bp)
+ { if(f->mode&SF_INIT)
+ (void)_sfmode(f,0,0);
+
+ if((f->flags&SF_RDWRSTR) == SF_RDWRSTR)
+ { SFSTRSIZE(f);
+ n = (f->data+f->here) - f->next;
+ }
+ else n = f->endb - f->next;
+
+ if(!bp)
+ return n;
+ else if(n > 0) /* size == 0 */
+ { *bp = (Void_t*)f->next;
+ return 0;
+ }
+ /* else fall down and fill buffer */
+ }
+
+ if(!(mode = f->flags&SF_READ) )
+ mode = SF_WRITE;
+ if((int)f->mode != mode && _sfmode(f,mode,0) < 0)
+ return -1;
+
+ *bp = sfreserve(f, sz <= 0 ? 0 : sz > f->size ? f->size : sz, 0);
+
+ if(*bp && sz >= 0)
+ return sz;
+
+ if((n = sfvalue(f)) > 0)
+ { *bp = (Void_t*)f->next;
+ if(sz < 0)
+ { f->mode |= SF_PEEK;
+ f->endr = f->endw = f->data;
+ }
+ else
+ { if(sz > n)
+ sz = n;
+ f->next += sz;
+ }
+ }
+
+ return (sz >= 0 && n >= sz) ? sz : n;
+}
diff --git a/src/lib/libast/sfio/sfpkrd.c b/src/lib/libast/sfio/sfpkrd.c
new file mode 100644
index 0000000..2572e6d
--- /dev/null
+++ b/src/lib/libast/sfio/sfpkrd.c
@@ -0,0 +1,325 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+#if !_PACKAGE_ast
+#ifndef FIONREAD
+#if _sys_ioctl
+#include <sys/ioctl.h>
+#endif
+#endif
+#endif
+
+/* Read/Peek a record from an unseekable device
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define STREAM_PEEK 001
+#define SOCKET_PEEK 002
+
+#if __STD_C
+ssize_t sfpkrd(int fd, Void_t* argbuf, size_t n, int rc, long tm, int action)
+#else
+ssize_t sfpkrd(fd, argbuf, n, rc, tm, action)
+int fd; /* file descriptor */
+Void_t* argbuf; /* buffer to read data */
+size_t n; /* buffer size */
+int rc; /* record character */
+long tm; /* time-out */
+int action; /* >0: peeking, if rc>=0, get action records,
+ <0: no peeking, if rc>=0, get -action records,
+ =0: no peeking, if rc>=0, must get a single record
+ */
+#endif
+{
+ reg ssize_t r;
+ reg int ntry, t;
+ reg char *buf = (char*)argbuf, *endbuf;
+
+ if(rc < 0 && tm < 0 && action <= 0)
+ return sysreadf(fd,buf,n);
+
+ t = (action > 0 || rc >= 0) ? (STREAM_PEEK|SOCKET_PEEK) : 0;
+#if !_stream_peek
+ t &= ~STREAM_PEEK;
+#endif
+#if !_socket_peek
+ t &= ~SOCKET_PEEK;
+#endif
+
+ for(ntry = 0; ntry < 2; ++ntry)
+ {
+ r = -1;
+#if _stream_peek
+ if((t&STREAM_PEEK) && (ntry == 1 || tm < 0) )
+ {
+#ifdef __sun
+ /*
+ * I_PEEK on stdin can hang rsh+ksh on solaris
+ * this kludge will have to do until sun^H^H^Horacle fixes I_PEEK/rsh
+ */
+ static int stream_peek;
+ if (stream_peek == 0) /* this will be done just once */
+ { char *e;
+ stream_peek = (
+ getenv("LOGNAME") == 0 &&
+ getenv("MAIL") == 0 &&
+ ((e = getenv("LANG")) == 0 || strcmp(e, "C") == 0) &&
+ ((e = getenv("PATH")) == 0 || strncmp(e, "/usr/bin:", 9) == 0)
+ ) ? -1 : 1;
+ }
+ if(stream_peek < 0)
+ t &= ~STREAM_PEEK;
+ else
+#endif
+ { struct strpeek pbuf;
+ pbuf.flags = 0;
+ pbuf.ctlbuf.maxlen = -1;
+ pbuf.ctlbuf.len = 0;
+ pbuf.ctlbuf.buf = NIL(char*);
+ pbuf.databuf.maxlen = n;
+ pbuf.databuf.buf = buf;
+ pbuf.databuf.len = 0;
+
+ if((r = ioctl(fd,I_PEEK,&pbuf)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ t &= ~STREAM_PEEK;
+ }
+ else
+ { t &= ~SOCKET_PEEK;
+ if(r > 0 && (r = pbuf.databuf.len) <= 0)
+ { if(action <= 0) /* read past eof */
+ r = sysreadf(fd,buf,1);
+ return r;
+ }
+ if(r == 0)
+ r = -1;
+ else if(r > 0)
+ break;
+ }
+ }
+ }
+#endif /* stream_peek */
+
+ if(ntry == 1)
+ break;
+
+ /* poll or select to see if data is present. */
+ while(tm >= 0 || action > 0 ||
+ /* block until there is data before peeking again */
+ ((t&STREAM_PEEK) && rc >= 0) ||
+ /* let select be interrupted instead of recv which autoresumes */
+ (t&SOCKET_PEEK) )
+ { r = -2;
+#if _lib_poll
+ if(r == -2)
+ {
+ struct pollfd po;
+ po.fd = fd;
+ po.events = POLLIN;
+ po.revents = 0;
+
+ if((r = SFPOLL(&po,1,tm)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ { errno = 0;
+ continue;
+ }
+ else r = -2;
+ }
+ else r = (po.revents&POLLIN) ? 1 : -1;
+ }
+#endif /*_lib_poll*/
+#if _lib_select
+ if(r == -2)
+ {
+#if _hpux_threads && vt_threaded
+#define fd_set int
+#endif
+ fd_set rd;
+ struct timeval tmb, *tmp;
+ FD_ZERO(&rd);
+ FD_SET(fd,&rd);
+ if(tm < 0)
+ tmp = NIL(struct timeval*);
+ else
+ { tmp = &tmb;
+ tmb.tv_sec = tm/SECOND;
+ tmb.tv_usec = (tm%SECOND)*SECOND;
+ }
+ r = select(fd+1,&rd,NIL(fd_set*),NIL(fd_set*),tmp);
+ if(r < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ { errno = 0;
+ continue;
+ }
+ else r = -2;
+ }
+ else r = FD_ISSET(fd,&rd) ? 1 : -1;
+ }
+#endif /*_lib_select*/
+ if(r == -2)
+ {
+#if !_lib_poll && !_lib_select /* both poll and select can't be used */
+#ifdef FIONREAD /* quick and dirty check for availability */
+ long nsec = tm < 0 ? 0 : (tm+999)/1000;
+ while(nsec > 0 && r < 0)
+ { long avail = -1;
+ if((r = ioctl(fd,FIONREAD,&avail)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ { errno = 0;
+ continue;
+ }
+ else /* ioctl failed completely */
+ { r = -2;
+ break;
+ }
+ }
+ else r = avail <= 0 ? -1 : (ssize_t)avail;
+
+ if(r < 0 && nsec-- > 0)
+ sleep(1);
+ }
+#endif
+#endif
+ }
+
+ if(r > 0) /* there is data now */
+ { if(action <= 0 && rc < 0)
+ return sysreadf(fd,buf,n);
+ else r = -1;
+ }
+ else if(tm >= 0) /* timeout exceeded */
+ return -1;
+ else r = -1;
+ break;
+ }
+
+#if _socket_peek
+ if(t&SOCKET_PEEK)
+ {
+#if __MACH__ && __APPLE__ /* check 10.4 recv(MSG_PEEK) bug that consumes pipe data */
+ static int recv_peek_pipe;
+ if (recv_peek_pipe == 0) /* this will be done just once */
+ { int fds[2], r;
+ char tst[2];
+
+ tst[0] = 'a'; tst[1] = 'z';
+
+ /* open a pipe and write to it */
+ recv_peek_pipe = 1;
+ if(recv_peek_pipe == 1 && pipe(fds) < 0)
+ recv_peek_pipe = -1;
+ if(recv_peek_pipe == 1 && write(fds[1], tst, 2) != 2)
+ recv_peek_pipe = -1;
+
+ /* try recv() to see if it gets anything */
+ tst[0] = tst[1] = 0;
+ if(recv_peek_pipe == 1 && (r = recv(fds[0], tst, 1, MSG_PEEK)) != 1)
+ recv_peek_pipe = -1;
+ if(recv_peek_pipe == 1 && tst[0] != 'a')
+ recv_peek_pipe = -1;
+
+ /* make sure that recv() did not consume data */
+ tst[0] = tst[1] = 0;
+ if(recv_peek_pipe == 1 && (r = recv(fds[0], tst, 2, MSG_PEEK)) != 2)
+ recv_peek_pipe = -1;
+ if(recv_peek_pipe == 1 && (tst[0] != 'a' || tst[1] != 'z') )
+ recv_peek_pipe = -1;
+
+ close(fds[0]);
+ close(fds[1]);
+ }
+
+ if(recv_peek_pipe < 0)
+ { struct stat st; /* recv should work on sockets */
+ if(fstat(fd, &st) < 0 || !S_ISSOCK(st.st_mode) )
+ { r = -1;
+ t &= ~SOCKET_PEEK;
+ }
+ }
+#endif
+ while((t&SOCKET_PEEK) && (r = recv(fd,(char*)buf,n,MSG_PEEK)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ errno = 0;
+ else t &= ~SOCKET_PEEK;
+ }
+ if(r >= 0)
+ { t &= ~STREAM_PEEK;
+ if(r > 0)
+ break;
+ else /* read past eof */
+ { if(action <= 0)
+ r = sysreadf(fd,buf,1);
+ return r;
+ }
+ }
+ }
+#endif
+ }
+
+ if(r < 0)
+ { if(tm >= 0 || action > 0)
+ return -1;
+ else /* get here means: tm < 0 && action <= 0 && rc >= 0 */
+ { /* number of records read at a time */
+ if((action = action ? -action : 1) > (int)n)
+ action = n;
+ r = 0;
+ while((t = sysreadf(fd,buf,action)) > 0)
+ { r += t;
+ for(endbuf = buf+t; buf < endbuf;)
+ if(*buf++ == rc)
+ action -= 1;
+ if(action == 0 || (int)(n-r) < action)
+ break;
+ }
+ return r == 0 ? t : r;
+ }
+ }
+
+ /* successful peek, find the record end */
+ if(rc >= 0)
+ { reg char* sp;
+
+ t = action == 0 ? 1 : action < 0 ? -action : action;
+ for(endbuf = (sp = buf)+r; sp < endbuf; )
+ if(*sp++ == rc)
+ if((t -= 1) == 0)
+ break;
+ r = sp - buf;
+ }
+
+ /* advance */
+ if(action <= 0)
+ r = sysreadf(fd,buf,r);
+
+ return r;
+}
diff --git a/src/lib/libast/sfio/sfpoll.c b/src/lib/libast/sfio/sfpoll.c
new file mode 100644
index 0000000..09110aa
--- /dev/null
+++ b/src/lib/libast/sfio/sfpoll.c
@@ -0,0 +1,250 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Poll a set of streams to see if any is available for I/O.
+** Ready streams are moved to front of array but retain the
+** same relative order.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfpoll(Sfio_t** fa, reg int n, int tm)
+#else
+int sfpoll(fa, n, tm)
+Sfio_t** fa; /* array of streams to poll */
+reg int n; /* number of streams in array */
+int tm; /* time in millisecs for select/poll */
+#endif
+{
+ reg int r, c, m, np, eintr;
+ reg Sfio_t* f;
+ reg int *status, *check;
+
+ if(n <= 0 || !fa)
+ return -1;
+
+ if(!(status = (int*)malloc(2*n*sizeof(int))) )
+ return -1;
+ check = status+n; /* streams that need polling */
+
+ /* a SF_READ stream is ready if there is buffered read data */
+#define RDREADY(f) (((f->mode&SF_READ) && f->next < f->endb) || \
+ ((f->mode&SF_WRITE) && f->proc && f->proc->ndata > 0) )
+
+ /* a SF_WRITE stream is ready if there is no write data */
+#define WRREADY(f) (!(f->mode&SF_WRITE) || f->next == f->data)
+
+#define HASAUXFD(f) (f->proc && f->proc->file >= 0 && f->proc->file != f->file)
+
+ for(r = c = eintr = 0; r < n; ++r) /* compute streams that must be checked */
+ { f = fa[r];
+ status[r] = 0;
+
+ /* terminate poll on interrupt? */
+ if(f->flags&SF_IOINTR)
+ eintr++;
+ /* check accessibility */
+ m = f->mode&SF_RDWR;
+ if((int)f->mode != m && _sfmode(f,m,0) < 0)
+ continue;
+
+ if((f->flags&SF_READ) && RDREADY(f))
+ status[r] |= SF_READ;
+
+ if((f->flags&SF_WRITE) && WRREADY(f))
+ status[r] |= SF_WRITE;
+
+ if((f->flags&SF_RDWR) == status[r])
+ continue;
+
+ /* has discipline, ask its opinion */
+ if(f->disc && f->disc->exceptf)
+ { if((m = (*f->disc->exceptf)(f,SF_DPOLL,&tm,f->disc)) < 0)
+ continue;
+ else if(m > 0)
+ { status[r] = m&SF_RDWR;
+ continue;
+ }
+ }
+
+ if(f->extent < 0) /* unseekable stream, must poll/select */
+ check[c++] = r;
+ else /* seekable streams are always ready */
+ { if(f->flags&SF_READ)
+ status[r] |= SF_READ;
+ if(f->flags&SF_WRITE)
+ status[r] |= SF_WRITE;
+ }
+ }
+ /* terminate poll on interrupt only if all streams marked SF_IOINTR */
+ eintr = eintr == n ? -1 : EINTR;
+
+ np = -1;
+#if _lib_poll
+ if(c > 0)
+ { struct pollfd* fds;
+
+ /* construct the poll array */
+ for(m = 0, r = 0; r < c; ++r, ++m)
+ { f = fa[check[r]];
+ if(HASAUXFD(f))
+ m += 1;
+ }
+ if(!(fds = (struct pollfd*)malloc(m*sizeof(struct pollfd))) )
+ return -1;
+
+ for(m = 0, r = 0; r < c; ++r, ++m)
+ { f = fa[check[r]];
+
+ fds[m].fd = f->file;
+ fds[m].events = fds[m].revents = 0;
+
+ if((f->flags&SF_WRITE) && !WRREADY(f) )
+ fds[m].events |= POLLOUT;
+
+ if((f->flags&SF_READ) && !RDREADY(f) )
+ { /* a sfpopen situation with two file descriptors */
+ if((f->mode&SF_WRITE) && HASAUXFD(f))
+ { m += 1;
+ fds[m].fd = f->proc->file;
+ fds[m].revents = 0;
+ }
+
+ fds[m].events |= POLLIN;
+ }
+ }
+
+ while((np = SFPOLL(fds,m,tm)) < 0 )
+ { if(errno == eintr || errno == EAGAIN)
+ errno = 0;
+ else break;
+ }
+ if(np > 0) /* poll succeeded */
+ np = c;
+
+ for(m = 0, r = 0; r < np; ++r, ++m)
+ { f = fa[check[r]];
+
+ if((f->flags&SF_WRITE) && !WRREADY(f) )
+ { if(fds[m].revents&POLLOUT)
+ status[check[r]] |= SF_WRITE;
+ }
+
+ if((f->flags&SF_READ) && !RDREADY(f))
+ { if((f->mode&SF_WRITE) && HASAUXFD(f))
+ m += 1;
+ if(fds[m].revents&POLLIN)
+ status[check[r]] |= SF_READ;
+ }
+ }
+
+ free((Void_t*)fds);
+ }
+#endif /*_lib_poll*/
+
+#if _lib_select
+ if(np < 0 && c > 0)
+ { fd_set rd, wr;
+ struct timeval tmb, *tmp;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ m = 0;
+ for(r = 0; r < c; ++r)
+ { f = fa[check[r]];
+
+ if(f->file > m)
+ m = f->file;
+
+ if((f->flags&SF_WRITE) && !WRREADY(f))
+ FD_SET(f->file,&wr);
+
+ if((f->flags&SF_READ) && !RDREADY(f))
+ { if((f->mode&SF_WRITE) && HASAUXFD(f))
+ { if(f->proc->file > m)
+ m = f->proc->file;
+ FD_SET(f->proc->file, &rd);
+ }
+ else FD_SET(f->file,&rd);
+ }
+ }
+ if(tm < 0)
+ tmp = NIL(struct timeval*);
+ else
+ { tmp = &tmb;
+ tmb.tv_sec = tm/SECOND;
+ tmb.tv_usec = (tm%SECOND)*SECOND;
+ }
+
+ while((np = select(m+1,&rd,&wr,NIL(fd_set*),tmp)) < 0 )
+ { if(errno == eintr)
+ errno = 0;
+ else break;
+ }
+ if(np > 0)
+ np = c;
+
+ for(r = 0; r < np; ++r)
+ { f = fa[check[r]];
+
+ if((f->flags&SF_WRITE) && !WRREADY(f) )
+ { if(FD_ISSET(f->file,&wr) )
+ status[check[r]] |= SF_WRITE;
+ }
+
+ if((f->flags&SF_READ) && !RDREADY(f) )
+ { if((f->mode&SF_WRITE) && HASAUXFD(f) )
+ { if(FD_ISSET(f->proc->file, &rd) )
+ status[check[r]] |= SF_READ;
+ }
+ else
+ { if(FD_ISSET(f->file,&rd) )
+ status[check[r]] |= SF_READ;
+ }
+ }
+ }
+ }
+#endif /*_lib_select*/
+
+ for(r = c = 0; c < n; ++c)
+ { if(status[c] == 0)
+ continue;
+
+ f = fa[c];
+ f->val = (ssize_t)status[c];
+
+ /* announce status */
+ if(f->disc && f->disc->exceptf)
+ (*f->disc->exceptf)(f,SF_READY,(Void_t*)(long)status[c],f->disc);
+
+ if(c > r) /* move to front of list */
+ { fa[c] = fa[r];
+ fa[r] = f;
+ }
+ r += 1;
+ }
+
+ free((Void_t*)status);
+ return r ? r : np < 0 ? -1 : 0;
+}
diff --git a/src/lib/libast/sfio/sfpool.c b/src/lib/libast/sfio/sfpool.c
new file mode 100644
index 0000000..dbfc045
--- /dev/null
+++ b/src/lib/libast/sfio/sfpool.c
@@ -0,0 +1,369 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Management of pools of streams.
+** If pf is not nil, f is pooled with pf and f becomes current;
+** otherwise, f is isolated from its pool. flag can be one of
+** 0 or SF_SHARE.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* Note that we do not free the space for a pool once it is allocated.
+** This is to prevent memory faults in calls such as sfsync(NULL) that walk the pool
+** link list and during such walks may free up streams&pools. Free pools will be
+** reused in newpool().
+*/
+#if __STD_C
+static int delpool(reg Sfpool_t* p)
+#else
+static int delpool(p)
+reg Sfpool_t* p;
+#endif
+{
+ POOLMTXENTER(p);
+
+ if(p->s_sf && p->sf != p->array)
+ free((Void_t*)p->sf);
+ p->mode = SF_AVAIL;
+
+ POOLMTXRETURN(p,0);
+}
+
+#if __STD_C
+static Sfpool_t* newpool(reg int mode)
+#else
+static Sfpool_t* newpool(mode)
+reg int mode;
+#endif
+{
+ reg Sfpool_t *p, *last = &_Sfpool;
+
+ /* look to see if there is a free pool */
+ for(last = &_Sfpool, p = last->next; p; last = p, p = p->next)
+ { if(p->mode == SF_AVAIL )
+ { p->mode = 0;
+ break;
+ }
+ }
+
+ if(!p)
+ { POOLMTXLOCK(last);
+
+ if(!(p = (Sfpool_t*) malloc(sizeof(Sfpool_t))) )
+ { POOLMTXUNLOCK(last);
+ return NIL(Sfpool_t*);
+ }
+
+ (void)vtmtxopen(&p->mutex, VT_INIT); /* initialize mutex */
+
+ p->mode = 0;
+ p->n_sf = 0;
+ p->next = NIL(Sfpool_t*);
+ last->next = p;
+
+ POOLMTXUNLOCK(last);
+ }
+
+ POOLMTXENTER(p);
+
+ p->mode = mode&SF_SHARE;
+ p->s_sf = sizeof(p->array)/sizeof(p->array[0]);
+ p->sf = p->array;
+
+ POOLMTXRETURN(p,p);
+}
+
+/* move a stream to head */
+#if __STD_C
+static int _sfphead(Sfpool_t* p, Sfio_t* f, int n)
+#else
+static int _sfphead(p, f, n)
+Sfpool_t* p; /* the pool */
+Sfio_t* f; /* the stream */
+int n; /* current position in pool */
+#endif
+{
+ reg Sfio_t* head;
+ reg ssize_t k, w, v;
+ reg int rv;
+
+ POOLMTXENTER(p);
+
+ if(n == 0)
+ POOLMTXRETURN(p,0);
+
+ head = p->sf[0];
+ if(SFFROZEN(head) )
+ POOLMTXRETURN(p,-1);
+
+ SFLOCK(head,0);
+ rv = -1;
+
+ if(!(p->mode&SF_SHARE) || (head->mode&SF_READ) || (f->mode&SF_READ) )
+ { if(SFSYNC(head) < 0)
+ goto done;
+ }
+ else /* shared pool of write-streams, data can be moved among streams */
+ { if(SFMODE(head,1) != SF_WRITE && _sfmode(head,SF_WRITE,1) < 0)
+ goto done;
+ /**/ASSERT(f->next == f->data);
+
+ v = head->next - head->data; /* pending data */
+ if((k = v - (f->endb-f->data)) <= 0)
+ k = 0;
+ else /* try to write out amount exceeding f's capacity */
+ { if((w = SFWR(head,head->data,k,head->disc)) == k)
+ v -= k;
+ else /* write failed, recover buffer then quit */
+ { if(w > 0)
+ { v -= w;
+ memcpy(head->data,(head->data+w),v);
+ }
+ head->next = head->data+v;
+ goto done;
+ }
+ }
+
+ /* move data from head to f */
+ if((head->data+k) != f->data )
+ memcpy(f->data,(head->data+k),v);
+ f->next = f->data+v;
+ }
+
+ f->mode &= ~SF_POOL;
+ head->mode |= SF_POOL;
+ head->next = head->endr = head->endw = head->data; /* clear write buffer */
+
+ p->sf[n] = head;
+ p->sf[0] = f;
+ rv = 0;
+
+done:
+ head->mode &= ~SF_LOCK; /* partially unlock because it's no longer head */
+
+ POOLMTXRETURN(p,rv);
+}
+
+/* delete a stream from its pool */
+#if __STD_C
+static int _sfpdelete(Sfpool_t* p, Sfio_t* f, int n)
+#else
+static int _sfpdelete(p, f, n)
+Sfpool_t* p; /* the pool */
+Sfio_t* f; /* the stream */
+int n; /* position in pool */
+#endif
+{
+ POOLMTXENTER(p);
+
+ p->n_sf -= 1;
+ for(; n < p->n_sf; ++n)
+ p->sf[n] = p->sf[n+1];
+
+ f->pool = NIL(Sfpool_t*);
+ f->mode &= ~SF_POOL;
+
+ if(p->n_sf == 0 || p == &_Sfpool)
+ { if(p != &_Sfpool)
+ delpool(p);
+ goto done;
+ }
+
+ /* !_Sfpool, make sure head stream is an open stream */
+ for(n = 0; n < p->n_sf; ++n)
+ if(!SFFROZEN(p->sf[n]))
+ break;
+ if(n < p->n_sf && n > 0)
+ { f = p->sf[n];
+ p->sf[n] = p->sf[0];
+ p->sf[0] = f;
+ }
+
+ /* head stream has SF_POOL off */
+ f = p->sf[0];
+ f->mode &= ~SF_POOL;
+ if(!SFFROZEN(f))
+ _SFOPEN(f);
+
+ /* if only one stream left, delete pool */
+ if(p->n_sf == 1 )
+ { _sfpdelete(p,f,0);
+ _sfsetpool(f);
+ }
+
+done:
+ POOLMTXRETURN(p,0);
+}
+
+#if __STD_C
+static int _sfpmove(reg Sfio_t* f, reg int type)
+#else
+static int _sfpmove(f,type)
+reg Sfio_t* f;
+reg int type; /* <0 : deleting, 0: move-to-front, >0: inserting */
+#endif
+{
+ reg Sfpool_t* p;
+ reg int n;
+
+ if(type > 0)
+ return _sfsetpool(f);
+ else
+ { if(!(p = f->pool) )
+ return -1;
+ for(n = p->n_sf-1; n >= 0; --n)
+ if(p->sf[n] == f)
+ break;
+ if(n < 0)
+ return -1;
+
+ return type == 0 ? _sfphead(p,f,n) : _sfpdelete(p,f,n);
+ }
+}
+
+#if __STD_C
+Sfio_t* sfpool(reg Sfio_t* f, reg Sfio_t* pf, reg int mode)
+#else
+Sfio_t* sfpool(f,pf,mode)
+reg Sfio_t* f;
+reg Sfio_t* pf;
+reg int mode;
+#endif
+{
+ int k;
+ Sfpool_t* p;
+ Sfio_t* rv;
+
+ _Sfpmove = _sfpmove;
+
+ if(!f) /* return head of pool of pf regardless of lock states */
+ { if(!pf)
+ return NIL(Sfio_t*);
+ else if(!pf->pool || pf->pool == &_Sfpool)
+ return pf;
+ else return pf->pool->sf[0];
+ }
+
+ if(f) /* check for permissions */
+ { SFMTXLOCK(f);
+ if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ { SFMTXUNLOCK(f);
+ return NIL(Sfio_t*);
+ }
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+ }
+ if(pf)
+ { SFMTXLOCK(pf);
+ if((pf->mode&SF_RDWR) != pf->mode && _sfmode(pf,0,0) < 0)
+ { if(f)
+ SFMTXUNLOCK(f);
+ SFMTXUNLOCK(pf);
+ return NIL(Sfio_t*);
+ }
+ if(pf->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(pf,NIL(Sfio_t*)));
+ }
+
+ /* f already in the same pool with pf */
+ if(f == pf || (pf && f->pool == pf->pool && f->pool != &_Sfpool) )
+ { if(f)
+ SFMTXUNLOCK(f);
+ if(pf)
+ SFMTXUNLOCK(pf);
+ return pf;
+ }
+
+ /* lock streams before internal manipulations */
+ rv = NIL(Sfio_t*);
+ SFLOCK(f,0);
+ if(pf)
+ SFLOCK(pf,0);
+
+ if(!pf) /* deleting f from its current pool */
+ { if((p = f->pool) != NIL(Sfpool_t*) && p != &_Sfpool)
+ for(k = 0; k < p->n_sf && pf == NIL(Sfio_t*); ++k)
+ if(p->sf[k] != f) /* a stream != f represents the pool */
+ pf = p->sf[k];
+ if(!pf) /* already isolated */
+ { rv = f; /* just return self */
+ goto done;
+ }
+
+ if(_sfpmove(f,-1) < 0 || _sfsetpool(f) < 0)
+ goto done; /* can't delete */
+
+ if(!pf->pool || pf->pool == &_Sfpool || pf->pool->n_sf <= 0 )
+ rv = pf;
+ else rv = pf->pool->sf[0]; /* return head of old pool */
+ goto done;
+ }
+
+ if(pf->pool && pf->pool != &_Sfpool) /* always use current mode */
+ mode = pf->pool->mode;
+
+ if(mode&SF_SHARE) /* can only have write streams */
+ { if(SFMODE(f,1) != SF_WRITE && _sfmode(f,SF_WRITE,1) < 0)
+ goto done;
+ if(SFMODE(pf,1) != SF_WRITE && _sfmode(pf,SF_WRITE,1) < 0)
+ goto done;
+ if(f->next > f->data && SFSYNC(f) < 0) /* start f clean */
+ goto done;
+ }
+
+ if(_sfpmove(f,-1) < 0) /* isolate f from current pool */
+ goto done;
+
+ if(!(p = pf->pool) || p == &_Sfpool) /* making a new pool */
+ { if(!(p = newpool(mode)) )
+ goto done;
+ if(_sfpmove(pf,-1) < 0) /* isolate pf from its current pool */
+ goto done;
+ pf->pool = p;
+ p->sf[0] = pf;
+ p->n_sf += 1;
+ }
+
+ f->pool = p; /* add f to pf's pool */
+ if(_sfsetpool(f) < 0)
+ goto done;
+
+ /**/ASSERT(p->sf[0] == pf && p->sf[p->n_sf-1] == f);
+ SFOPEN(pf,0);
+ SFOPEN(f,0);
+ if(_sfpmove(f,0) < 0) /* make f head of pool */
+ goto done;
+ rv = pf;
+
+done:
+ if(f)
+ { SFOPEN(f,0);
+ SFMTXUNLOCK(f);
+ }
+ if(pf)
+ { SFOPEN(pf,0);
+ SFMTXUNLOCK(pf);
+ }
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfpopen.c b/src/lib/libast/sfio/sfpopen.c
new file mode 100644
index 0000000..ed3ea7f
--- /dev/null
+++ b/src/lib/libast/sfio/sfpopen.c
@@ -0,0 +1,293 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Create a coprocess.
+** Written by Kiem-Phong Vo.
+*/
+
+#if _PACKAGE_ast
+#include <proc.h>
+#else
+
+#define EXIT_NOTFOUND 127
+
+#define READ 0
+#define WRITE 1
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+static char Meta[1<<CHAR_BIT], **Path;
+
+/* execute command directly if possible; else use the shell */
+#if __STD_C
+static void execute(const char* argcmd)
+#else
+static void execute(argcmd)
+char* argcmd;
+#endif
+{
+ reg char *s, *cmd, **argv, **p, *interp;
+ reg int n;
+
+ /* define interpreter */
+ if(!(interp = getenv("SHELL")) || !interp[0])
+ interp = "/bin/sh";
+
+ if(strcmp(interp,"/bin/sh") != 0 && strcmp(interp,"/bin/ksh") != 0 )
+ { if(access(interp,X_OK) == 0)
+ goto do_interp;
+ else interp = "/bin/sh";
+ }
+
+ /* if there is a meta character, let the shell do it */
+ for(s = (char*)argcmd; *s; ++s)
+ if(Meta[(uchar)s[0]])
+ goto do_interp;
+
+ /* try to construct argv */
+ if(!(cmd = (char*)malloc(strlen(argcmd)+1)) )
+ goto do_interp;
+ strcpy(cmd,argcmd);
+ if(!(argv = (char**)malloc(16*sizeof(char*))) )
+ goto do_interp;
+ for(n = 0, s = cmd;; )
+ { while(isspace(s[0]))
+ s += 1;
+ if(s[0] == 0)
+ break;
+
+ /* new argument */
+ argv[n++] = s;
+ if((n%16) == 0 && !(argv = (char**)realloc(argv,(n+16)*sizeof(char*))) )
+ goto do_interp;
+
+ /* make this into a C string */
+ while(s[0] && !isspace(s[0]))
+ s += 1;
+ if(!s[0])
+ *s++ = 0;
+ }
+ if(n == 0)
+ goto do_interp;
+ argv[n] = NIL(char*);
+
+ /* get the command name */
+ cmd = argv[0];
+ for(s = cmd+strlen(cmd)-1; s >= cmd; --s)
+ if(*s == '/')
+ break;
+ argv[0] = s+1;
+
+ /* Non-standard pathnames as in nDFS should be handled by the shell */
+ for(s = cmd+strlen(cmd)-1; s >= cmd+2; --s)
+ if(s[0] == '.' && s[-1] == '.' && s[-2] == '.')
+ goto do_interp;
+
+ if(cmd[0] == '/' ||
+ (cmd[0] == '.' && cmd[1] == '/') ||
+ (cmd[0] == '.' && cmd[1] == '.' && cmd[2] == '/') )
+ { if(access(cmd,X_OK) != 0)
+ goto do_interp;
+ else execv(cmd,argv);
+ }
+ else
+ { for(p = Path; *p; ++p)
+ { s = sfprints("%s/%s", *p, cmd);
+ if(access(s,X_OK) == 0)
+ execv(s,argv);
+ }
+ }
+
+ /* if get here, let the interpreter do it */
+do_interp:
+ for(s = interp+strlen(interp)-1; s >= interp; --s)
+ if(*s == '/')
+ break;
+ execl(interp, s+1, "-c", argcmd, NIL(char*));
+ _exit(EXIT_NOTFOUND);
+}
+
+#endif /*_PACKAGE_ast*/
+
+#if __STD_C
+Sfio_t* sfpopen(Sfio_t* f, const char* command, const char* mode)
+#else
+Sfio_t* sfpopen(f,command,mode)
+Sfio_t* f;
+char* command; /* command to execute */
+char* mode; /* mode of the stream */
+#endif
+{
+#if _PACKAGE_ast
+ reg Proc_t* proc;
+ reg int sflags;
+ reg long flags;
+ reg int pflags;
+ char* av[4];
+
+ if (!command || !command[0] || !mode)
+ return 0;
+ sflags = _sftype(mode, NiL, NiL);
+
+ if(f == (Sfio_t*)(-1))
+ { /* stdio compatibility mode */
+ f = NIL(Sfio_t*);
+ pflags = 1;
+ }
+ else pflags = 0;
+
+ flags = 0;
+ if (sflags & SF_READ)
+ flags |= PROC_READ;
+ if (sflags & SF_WRITE)
+ flags |= PROC_WRITE;
+ av[0] = "sh";
+ av[1] = "-c";
+ av[2] = (char*)command;
+ av[3] = 0;
+ if (!(proc = procopen(0, av, 0, 0, flags)))
+ return 0;
+ if (!(f = sfnew(f, NIL(Void_t*), (size_t)SF_UNBOUND,
+ (sflags&SF_READ) ? proc->rfd : proc->wfd, sflags|((sflags&SF_RDWR)?0:SF_READ))) ||
+ _sfpopen(f, (sflags&SF_READ) ? proc->wfd : -1, proc->pid, pflags) < 0)
+ {
+ if (f) sfclose(f);
+ procclose(proc);
+ return 0;
+ }
+ procfree(proc);
+ return f;
+#else
+ reg int pid, fd, pkeep, ckeep, sflags;
+ int stdio, parent[2], child[2];
+ Sfio_t sf;
+
+ /* set shell meta characters */
+ if(Meta[0] == 0)
+ { reg char* s;
+ Meta[0] = 1;
+ for(s = "!@#$%&*(){}[]:;<>~`'|\"\\"; *s; ++s)
+ Meta[(uchar)s[0]] = 1;
+ }
+ if(!Path)
+ Path = _sfgetpath("PATH");
+
+ /* sanity check */
+ if(!command || !command[0] || !mode)
+ return NIL(Sfio_t*);
+ sflags = _sftype(mode,NIL(int*),NIL(int*));
+
+ /* make pipes */
+ parent[0] = parent[1] = child[0] = child[1] = -1;
+ if(sflags&SF_RDWR)
+ { if(syspipef(parent) < 0)
+ goto error;
+ if((sflags&SF_RDWR) == SF_RDWR && syspipef(child) < 0)
+ goto error;
+ }
+
+ switch((pid = fork()) )
+ {
+ default : /* in parent process */
+ if(sflags&SF_READ)
+ { pkeep = READ; ckeep = WRITE; }
+ else { pkeep = WRITE; ckeep = READ; }
+
+ if(f == (Sfio_t*)(-1))
+ { /* stdio compatibility mode */
+ f = NIL(Sfio_t*);
+ stdio = 1;
+ }
+ else stdio = 0;
+
+ /* make the streams */
+ if(!(f = sfnew(f,NIL(Void_t*),(size_t)SF_UNBOUND,parent[pkeep],sflags|((sflags&SF_RDWR)?0:SF_READ))))
+ goto error;
+ if(sflags&SF_RDWR)
+ { CLOSE(parent[!pkeep]);
+ SETCLOEXEC(parent[pkeep]);
+ if((sflags&SF_RDWR) == SF_RDWR)
+ { CLOSE(child[!ckeep]);
+ SETCLOEXEC(child[ckeep]);
+ }
+ }
+
+ /* save process info */
+ fd = (sflags&SF_RDWR) == SF_RDWR ? child[ckeep] : -1;
+ if(_sfpopen(f,fd,pid,stdio) < 0)
+ { (void)sfclose(f);
+ goto error;
+ }
+
+ return f;
+
+ case 0 : /* in child process */
+ /* determine what to keep */
+ if(sflags&SF_READ)
+ { pkeep = WRITE; ckeep = READ; }
+ else { pkeep = READ; ckeep = WRITE; }
+
+ /* zap fd that we don't need */
+ if(sflags&SF_RDWR)
+ { CLOSE(parent[!pkeep]);
+ if((sflags&SF_RDWR) == SF_RDWR)
+ CLOSE(child[!ckeep]);
+ }
+
+ /* use sfsetfd to make these descriptors the std-ones */
+ SFCLEAR(&sf,NIL(Vtmutex_t*));
+
+ /* must be careful so not to close something useful */
+ if((sflags&SF_RDWR) == SF_RDWR && pkeep == child[ckeep])
+ if((child[ckeep] = sysdupf(pkeep)) < 0)
+ _exit(EXIT_NOTFOUND);
+
+ if(sflags&SF_RDWR)
+ { if (parent[pkeep] != pkeep)
+ { sf.file = parent[pkeep];
+ CLOSE(pkeep);
+ if(sfsetfd(&sf,pkeep) != pkeep)
+ _exit(EXIT_NOTFOUND);
+ }
+ if((sflags&SF_RDWR) == SF_RDWR && child[ckeep] != ckeep)
+ { sf.file = child[ckeep];
+ CLOSE(ckeep);
+ if(sfsetfd(&sf,ckeep) != ckeep)
+ _exit(EXIT_NOTFOUND);
+ }
+ }
+
+ execute(command);
+ return NIL(Sfio_t*);
+
+ case -1 : /* error */
+ error:
+ if(parent[0] >= 0)
+ { CLOSE(parent[0]); CLOSE(parent[1]); }
+ if(child[0] >= 0)
+ { CLOSE(child[0]); CLOSE(child[1]); }
+ return NIL(Sfio_t*);
+ }
+#endif /*_PACKAGE_ast*/
+}
diff --git a/src/lib/libast/sfio/sfprintf.c b/src/lib/libast/sfio/sfprintf.c
new file mode 100644
index 0000000..50b0804
--- /dev/null
+++ b/src/lib/libast/sfio/sfprintf.c
@@ -0,0 +1,114 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Print data with a given format
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfprintf(Sfio_t* f, const char* form, ...)
+#else
+int sfprintf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ reg int rv;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ reg Sfio_t* f;
+ reg char* form;
+ va_start(args);
+ f = va_arg(args,Sfio_t*);
+ form = va_arg(args,char*);
+#endif
+ rv = sfvprintf(f,form,args);
+
+ va_end(args);
+ return rv;
+}
+
+#if __STD_C
+ssize_t sfvsprintf(char* s, size_t n, const char* form, va_list args)
+#else
+ssize_t sfvsprintf(s, n, form, args)
+char* s;
+size_t n;
+char* form;
+va_list args;
+#endif
+{
+ Sfio_t *f;
+ ssize_t rv;
+
+ /* make a temp stream */
+ if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND,
+ -1,SF_WRITE|SF_STRING)) )
+ return -1;
+
+ if((rv = sfvprintf(f,form,args)) >= 0 && s && n > 0)
+ { if((rv+1) >= n)
+ n--;
+ else
+ n = rv;
+ memcpy(s, f->data, n);
+ s[n] = 0;
+ }
+
+ sfclose(f);
+
+ _Sfi = rv;
+
+ return rv;
+}
+
+#if __STD_C
+ssize_t sfsprintf(char* s, size_t n, const char* form, ...)
+#else
+ssize_t sfsprintf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ ssize_t rv;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ reg char* s;
+ reg size_t n;
+ reg char* form;
+ va_start(args);
+ s = va_arg(args,char*);
+ n = va_arg(args,size_t);
+ form = va_arg(args,char*);
+#endif
+
+ rv = sfvsprintf(s,n,form,args);
+ va_end(args);
+
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfprints.c b/src/lib/libast/sfio/sfprints.c
new file mode 100644
index 0000000..d69cc34
--- /dev/null
+++ b/src/lib/libast/sfio/sfprints.c
@@ -0,0 +1,125 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Construct a string with the given format and data.
+** These functions allocate space as necessary to store the string.
+** This avoids overflow problems typical with sprintf() in stdio.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+char* sfvprints(const char* form, va_list args)
+#else
+char* sfvprints(form, args)
+char* form;
+va_list args;
+#endif
+{
+ reg int rv;
+ static Sfio_t* f;
+
+ /* make a fake stream */
+ if(!f &&
+ !(f = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND,
+ -1,SF_WRITE|SF_STRING)) )
+ return NIL(char*);
+
+ sfseek(f,(Sfoff_t)0,SEEK_SET);
+ rv = sfvprintf(f,form,args);
+
+ if(rv < 0 || sfputc(f,'\0') < 0)
+ return NIL(char*);
+
+ _Sfi = (f->next - f->data) - 1;
+ return (char*)f->data;
+}
+
+#if __STD_C
+char* sfprints(const char* form, ...)
+#else
+char* sfprints(va_alist)
+va_dcl
+#endif
+{
+ char* s;
+ va_list args;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ char *form;
+ va_start(args);
+ form = va_arg(args,char*);
+#endif
+ s = sfvprints(form, args);
+ va_end(args);
+
+ return s;
+}
+
+#if __STD_C
+ssize_t sfvaprints(char** sp, const char* form, va_list args)
+#else
+ssize_t sfvaprints(sp, form, args)
+char** sp;
+char* form;
+va_list args;
+#endif
+{
+ char *s;
+ ssize_t n;
+
+ if(!sp || !(s = sfvprints(form,args)) )
+ return -1;
+ else
+ { if(!(*sp = (char*)malloc(n = strlen(s)+1)) )
+ return -1;
+ memcpy(*sp, s, n);
+ return n-1;
+ }
+}
+
+#if __STD_C
+ssize_t sfaprints(char** sp, const char* form, ...)
+#else
+ssize_t sfaprints(va_alist)
+va_dcl
+#endif
+{
+ ssize_t n;
+ va_list args;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ char **sp, *form;
+ va_start(args);
+ sp = va_arg(args, char**);
+ form = va_arg(args, char*);
+#endif
+ n = sfvaprints(sp, form, args);
+ va_end(args);
+
+ return n;
+}
diff --git a/src/lib/libast/sfio/sfpurge.c b/src/lib/libast/sfio/sfpurge.c
new file mode 100644
index 0000000..c3b4106
--- /dev/null
+++ b/src/lib/libast/sfio/sfpurge.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Delete all pending data in the buffer
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfpurge(Sfio_t* f)
+#else
+int sfpurge(f)
+Sfio_t* f;
+#endif
+{
+ reg int mode;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode|SF_SYNCED,0) < 0)
+ SFMTXRETURN(f, -1);
+
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_PURGE,(Void_t*)((int)1),f->disc);
+
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ /* cannot purge read string streams */
+ if((f->flags&SF_STRING) && (f->mode&SF_READ) )
+ goto done;
+
+ SFLOCK(f,0);
+
+ /* if memory map must be a read stream, pretend data is gone */
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { f->here -= f->endb - f->next;
+ if(f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ (void)SFSK(f,f->here,SEEK_SET,f->disc);
+ }
+ SFOPEN(f,0);
+ SFMTXRETURN(f, 0);
+ }
+#endif
+
+ switch(f->mode&~SF_LOCK)
+ {
+ default :
+ SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ case SF_WRITE :
+ f->next = f->data;
+ if(!f->proc || !(f->flags&SF_READ) || !(f->mode&SF_WRITE) )
+ break;
+
+ /* 2-way pipe, must clear read buffer */
+ (void)_sfmode(f,SF_READ,1);
+ /* fall through */
+ case SF_READ:
+ if(f->extent >= 0 && f->endb > f->next)
+ { f->here -= f->endb-f->next;
+ (void)SFSK(f,f->here,SEEK_SET,f->disc);
+ }
+ f->endb = f->next = f->data;
+ break;
+ }
+
+ SFOPEN(f,0);
+
+done:
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_PURGE,(Void_t*)((int)0),f->disc);
+
+ SFMTXRETURN(f, 0);
+}
diff --git a/src/lib/libast/sfio/sfputd.c b/src/lib/libast/sfio/sfputd.c
new file mode 100644
index 0000000..3129cd5
--- /dev/null
+++ b/src/lib/libast/sfio/sfputd.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputd
+
+#if __STD_C
+int sfputd(reg Sfio_t* f, Sfdouble_t d)
+#else
+int sfputd(f,d)
+reg Sfio_t* f;
+reg Sfdouble_t d;
+#endif
+{
+ return __sf_putd(f,d);
+}
diff --git a/src/lib/libast/sfio/sfputl.c b/src/lib/libast/sfio/sfputl.c
new file mode 100644
index 0000000..ceaa6b9
--- /dev/null
+++ b/src/lib/libast/sfio/sfputl.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputl
+
+#if __STD_C
+int sfputl(reg Sfio_t* f, Sflong_t l)
+#else
+int sfputl(f,l)
+reg Sfio_t* f;
+reg Sflong_t l;
+#endif
+{
+ return __sf_putl(f,l);
+}
diff --git a/src/lib/libast/sfio/sfputm.c b/src/lib/libast/sfio/sfputm.c
new file mode 100644
index 0000000..8082a7b
--- /dev/null
+++ b/src/lib/libast/sfio/sfputm.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputm
+
+#if __STD_C
+int sfputm(Sfio_t* f, Sfulong_t u, Sfulong_t m)
+#else
+int sfputm(f,u,m)
+Sfio_t* f;
+Sfulong_t u;
+Sfulong_t m;
+#endif
+{
+ return __sf_putm(f, u, m);
+}
diff --git a/src/lib/libast/sfio/sfputr.c b/src/lib/libast/sfio/sfputr.c
new file mode 100644
index 0000000..21bfb0a
--- /dev/null
+++ b/src/lib/libast/sfio/sfputr.c
@@ -0,0 +1,136 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Put out a null-terminated string
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+ssize_t sfputr(Sfio_t* f, const char* s, int rc)
+#else
+ssize_t sfputr(f,s,rc)
+Sfio_t* f; /* write to this stream */
+char* s; /* string to write */
+int rc; /* record separator. */
+#endif
+{
+ ssize_t p, n, w, sn;
+ uchar *ps;
+ char *ss;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,0);
+
+ f->val = sn = -1; ss = (char*)s;
+ for(w = 0; (*s || rc >= 0); )
+ { /* need to communicate string size to exception handler */
+ if((f->flags&SF_STRING) && f->next >= f->endb )
+ { sn = sn < 0 ? strlen(s) : (sn - (s-ss));
+ ss = (char*)s; /* save current checkpoint */
+ f->val = sn + (rc >= 0 ? 1 : 0); /* space requirement */
+ f->bits |= SF_PUTR; /* tell sfflsbuf to use f->val */
+ }
+
+ SFWPEEK(f,ps,p);
+ f->bits &= ~SF_PUTR; /* remove any trace of this */
+
+ if(p < 0 ) /* something not right about buffering */
+ break;
+
+ if(p == 0 || (f->flags&SF_WHOLE) )
+ { n = sn < 0 ? strlen(s) : sn - (s-ss);
+ if(p >= (n + (rc < 0 ? 0 : 1)) )
+ { /* buffer can hold everything */
+ if(n > 0)
+ { memcpy(ps, s, n);
+ ps += n;
+ w += n;
+ }
+ if(rc >= 0)
+ { *ps++ = rc;
+ w += 1;
+ }
+ f->next = ps;
+ }
+ else
+ { /* create a reserve buffer to hold data */
+ Sfrsrv_t* rsrv;
+
+ p = n + (rc >= 0 ? 1 : 0);
+ if(!(rsrv = _sfrsrv(f, p)) )
+ n = 0;
+ else
+ { if(n > 0)
+ memcpy(rsrv->data, s, n);
+ if(rc >= 0)
+ rsrv->data[n] = rc;
+ if((n = SFWRITE(f,rsrv->data,p)) < 0 )
+ n = 0;
+ }
+
+ w += n;
+ }
+ break;
+ }
+
+ if(*s == 0)
+ { *ps++ = rc;
+ f->next = ps;
+ w += 1;
+ break;
+ }
+
+#if _lib_memccpy && !__ia64 /* these guys may never get it right */
+ if((ps = (uchar*)memccpy(ps,s,'\0',p)) != NIL(uchar*))
+ ps -= 1;
+ else ps = f->next+p;
+ s += ps - f->next;
+#else
+ for(; p > 0; --p, ++ps, ++s)
+ if((*ps = *s) == 0)
+ break;
+#endif
+ w += ps - f->next;
+ f->next = ps;
+ }
+
+ /* sync unseekable shared streams */
+ if(f->extent < 0 && (f->flags&SF_SHARE) )
+ (void)SFFLSBUF(f,-1);
+
+ /* check for line buffering */
+ else if((f->flags&SF_LINE) && !(f->flags&SF_STRING) && (n = f->next-f->data) > 0)
+ { if(n > w)
+ n = w;
+ f->next -= n;
+ (void)SFWRITE(f,(Void_t*)f->next,n);
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, w);
+}
diff --git a/src/lib/libast/sfio/sfputu.c b/src/lib/libast/sfio/sfputu.c
new file mode 100644
index 0000000..17f1567
--- /dev/null
+++ b/src/lib/libast/sfio/sfputu.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputu
+
+#if __STD_C
+int sfputu(reg Sfio_t* f, Sfulong_t u)
+#else
+int sfputu(f,u)
+reg Sfio_t* f;
+reg Sfulong_t u;
+#endif
+{
+ return __sf_putu(f,u);
+}
diff --git a/src/lib/libast/sfio/sfraise.c b/src/lib/libast/sfio/sfraise.c
new file mode 100644
index 0000000..7ea4ef3
--- /dev/null
+++ b/src/lib/libast/sfio/sfraise.c
@@ -0,0 +1,107 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Invoke event handlers for a stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static int _sfraiseall(int type, Void_t* data)
+#else
+static int _sfraiseall(type, data)
+int type; /* type of event */
+Void_t* data; /* associated data */
+#endif
+{
+ Sfio_t *f;
+ Sfpool_t *p, *next;
+ int n, rv;
+
+ rv = 0;
+ for(p = &_Sfpool; p; p = next)
+ {
+ for(next = p->next; next; next = next->next)
+ if(next->n_sf > 0)
+ break;
+ for(n = 0; n < p->n_sf; ++n)
+ { f = p->sf[n];
+ if(sfraise(f, type, data) < 0)
+ rv -= 1;
+ }
+ }
+ return rv;
+}
+
+#if __STD_C
+int sfraise(Sfio_t* f, int type, Void_t* data)
+#else
+int sfraise(f, type, data)
+Sfio_t* f; /* stream */
+int type; /* type of event */
+Void_t* data; /* associated data */
+#endif
+{
+ reg Sfdisc_t *disc, *next, *d;
+ reg int local, rv;
+ SFMTXDECL(f);
+
+ if(!f)
+ return _sfraiseall(type,data);
+
+ SFMTXENTER(f, -1);
+
+ GETLOCAL(f,local);
+ if(!SFKILLED(f) &&
+ !(local &&
+ (type == SF_NEW || type == SF_CLOSING ||
+ type == SF_FINAL || type == SF_ATEXIT)) &&
+ SFMODE(f,local) != (f->mode&SF_RDWR) && _sfmode(f,0,local) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,local);
+
+ for(disc = f->disc; disc; )
+ { next = disc->disc;
+ if(type == SF_FINAL)
+ f->disc = next;
+
+ if(disc->exceptf)
+ { SFOPEN(f,0);
+ if((rv = (*disc->exceptf)(f,type,data,disc)) != 0 )
+ SFMTXRETURN(f, rv);
+ SFLOCK(f,0);
+ }
+
+ if((disc = next) )
+ { /* make sure that "next" hasn't been popped */
+ for(d = f->disc; d; d = d->disc)
+ if(d == disc)
+ break;
+ if(!d)
+ disc = f->disc;
+ }
+ }
+
+ SFOPEN(f,local);
+ SFMTXRETURN(f, 0);
+}
diff --git a/src/lib/libast/sfio/sfrd.c b/src/lib/libast/sfio/sfrd.c
new file mode 100644
index 0000000..09a493c
--- /dev/null
+++ b/src/lib/libast/sfio/sfrd.c
@@ -0,0 +1,317 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Internal function to do a hard read.
+** This knows about discipline and memory mapping, peek read.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* synchronize unseekable write streams */
+#if __STD_C
+static void _sfwrsync(void)
+#else
+static void _sfwrsync()
+#endif
+{ reg Sfpool_t* p;
+ reg Sfio_t* f;
+ reg int n;
+
+ /* sync all pool heads */
+ for(p = _Sfpool.next; p; p = p->next)
+ { if(p->n_sf <= 0)
+ continue;
+ f = p->sf[0];
+ if(!SFFROZEN(f) && f->next > f->data &&
+ (f->mode&SF_WRITE) && f->extent < 0 )
+ (void)_sfflsbuf(f,-1);
+ }
+
+ /* and all the ones in the discrete pool */
+ for(n = 0; n < _Sfpool.n_sf; ++n)
+ { f = _Sfpool.sf[n];
+
+ if(!SFFROZEN(f) && f->next > f->data &&
+ (f->mode&SF_WRITE) && f->extent < 0 )
+ (void)_sfflsbuf(f,-1);
+ }
+}
+
+#if __STD_C
+ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+ssize_t sfrd(f,buf,n,disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ Sfoff_t r;
+ reg Sfdisc_t* dc;
+ reg int local, rcrv, dosync, oerrno;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+ if((rcrv = f->mode & (SF_RC|SF_RV)) )
+ f->mode &= ~(SF_RC|SF_RV);
+ f->bits &= ~SF_JUSTSEEK;
+
+ if(f->mode&SF_PKRD)
+ SFMTXRETURN(f, -1);
+
+ if(!local && !(f->bits&SF_DCDOWN)) /* an external user's call */
+ { if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, -1);
+ if(f->next < f->endb)
+ { if(SFSYNC(f) < 0)
+ SFMTXRETURN(f, -1);
+ if((f->mode&(SF_SYNCED|SF_READ)) == (SF_SYNCED|SF_READ) )
+ { f->endb = f->next = f->endr = f->data;
+ f->mode &= ~SF_SYNCED;
+ }
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f, f->data, f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endb = f->endr = f->endw = f->data;
+ }
+ }
+
+ for(dosync = 0;;)
+ { /* stream locked by sfsetfd() */
+ if(!(f->flags&SF_STRING) && f->file < 0)
+ SFMTXRETURN(f, 0);
+
+ f->flags &= ~(SF_EOF|SF_ERROR);
+
+ dc = disc;
+ if(f->flags&SF_STRING)
+ { if((r = (f->data+f->extent) - f->next) < 0)
+ r = 0;
+ if(r <= 0)
+ goto do_except;
+ SFMTXRETURN(f, (ssize_t)r);
+ }
+
+ /* warn that a read is about to happen */
+ SFDISC(f,dc,readf);
+ if(dc && dc->exceptf && (f->flags&SF_IOCHECK) )
+ { reg int rv;
+ if(local)
+ SETLOCAL(f);
+ if((rv = _sfexcept(f,SF_READ,n,dc)) > 0)
+ n = rv;
+ else if(rv < 0)
+ { f->flags |= SF_ERROR;
+ SFMTXRETURN(f, (ssize_t)rv);
+ }
+ }
+
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { reg ssize_t a, round;
+ sfstat_t st;
+
+ /* determine if we have to copy data to buffer */
+ if((uchar*)buf >= f->data && (uchar*)buf <= f->endb)
+ { n += f->endb - f->next;
+ buf = NIL(char*);
+ }
+
+ /* actual seek location */
+ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) &&
+ (r = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc)) != f->here)
+ f->here = r;
+ else f->here -= f->endb-f->next;
+
+ /* before mapping, make sure we have data to map */
+ if((f->flags&SF_SHARE) || (size_t)(r = f->extent-f->here) < n)
+ { if((r = sysfstatf(f->file,&st)) < 0)
+ goto do_except;
+ if((r = (f->extent = st.st_size) - f->here) <= 0 )
+ { r = 0; /* eof */
+ goto do_except;
+ }
+ }
+
+ /* make sure current position is page aligned */
+ if((a = (size_t)(f->here%_Sfpage)) != 0)
+ { f->here -= a;
+ r += a;
+ }
+
+ /* map minimal requirement */
+ if(r > (round = (1 + (n+a)/f->size)*f->size) )
+ r = round;
+
+ if(f->data)
+ SFMUNMAP(f, f->data, f->endb-f->data);
+
+ for(;;)
+ { f->data = (uchar*) sysmmapf((caddr_t)0, (size_t)r,
+ (PROT_READ|PROT_WRITE),
+ MAP_PRIVATE,
+ f->file, (sfoff_t)f->here);
+ if(f->data && (caddr_t)f->data != (caddr_t)(-1))
+ break;
+ else
+ { f->data = NIL(uchar*);
+ if((r >>= 1) < (_Sfpage*SF_NMAP) ||
+ (errno != EAGAIN && errno != ENOMEM) )
+ break;
+ }
+ }
+
+ if(f->data)
+ { if(f->bits&SF_SEQUENTIAL)
+ SFMMSEQON(f,f->data,r);
+ f->next = f->data+a;
+ f->endr = f->endb = f->data+r;
+ f->endw = f->data;
+ f->here += r;
+
+ /* make known our seek location */
+ (void)SFSK(f,f->here,SEEK_SET,dc);
+
+ if(buf)
+ { if(n > (size_t)(r-a))
+ n = (ssize_t)(r-a);
+ memcpy(buf,f->next,n);
+ f->next += n;
+ }
+ else n = f->endb - f->next;
+
+ SFMTXRETURN(f, n);
+ }
+ else
+ { r = -1;
+ f->here += a;
+
+ /* reset seek pointer to its physical location */
+ (void)SFSK(f,f->here,SEEK_SET,dc);
+
+ /* make a buffer */
+ (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+
+ if(!buf)
+ { buf = (Void_t*)f->data;
+ n = f->size;
+ }
+ }
+ }
+#endif
+
+ /* sync unseekable write streams to prevent deadlock */
+ if(!dosync && f->extent < 0)
+ { dosync = 1;
+ _sfwrsync();
+ }
+
+ /* make sure file pointer is right */
+ if(f->extent >= 0 && (f->flags&SF_SHARE) )
+ { if(!(f->flags&SF_PUBLIC) )
+ f->here = SFSK(f,f->here,SEEK_SET,dc);
+ else f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc);
+ }
+
+ oerrno = errno;
+ errno = 0;
+
+ if(dc && dc->readf)
+ { int share = f->flags&SF_SHARE;
+
+ if(rcrv) /* pass on rcrv for possible continuations */
+ f->mode |= rcrv;
+ /* tell readf that no peeking necessary */
+ else f->flags &= ~SF_SHARE;
+
+ SFDCRD(f,buf,n,dc,r);
+
+ /* reset flags */
+ if(rcrv)
+ f->mode &= ~rcrv;
+ else f->flags |= share;
+ }
+ else if(SFISNULL(f))
+ r = 0;
+ else if(f->extent < 0 && (f->flags&SF_SHARE) && rcrv)
+ { /* try peek read */
+ r = sfpkrd(f->file, (char*)buf, n,
+ (rcrv&SF_RC) ? (int)f->getr : -1,
+ -1L, (rcrv&SF_RV) ? 1 : 0);
+ if(r > 0)
+ { if(rcrv&SF_RV)
+ f->mode |= SF_PKRD;
+ else f->mode |= SF_RC;
+ }
+ }
+ else r = sysreadf(f->file,buf,n);
+
+ if(errno == 0 )
+ errno = oerrno;
+
+ if(r > 0 )
+ { if(!(f->bits&SF_DCDOWN) ) /* not a continuation call */
+ { if(!(f->mode&SF_PKRD) )
+ { f->here += r;
+ if(f->extent >= 0 && f->extent < f->here)
+ f->extent = f->here;
+ }
+ if((uchar*)buf >= f->data &&
+ (uchar*)buf < f->data+f->size)
+ f->endb = f->endr = ((uchar*)buf) + r;
+ }
+
+ SFMTXRETURN(f, (ssize_t)r);
+ }
+
+ do_except:
+ if(local)
+ SETLOCAL(f);
+ switch(_sfexcept(f,SF_READ,(ssize_t)r,dc))
+ {
+ case SF_ECONT :
+ goto do_continue;
+ case SF_EDONE :
+ n = local ? 0 : (ssize_t)r;
+ SFMTXRETURN(f,n);
+ case SF_EDISC :
+ if(!local && !(f->flags&SF_STRING))
+ goto do_continue;
+ /* else fall thru */
+ case SF_ESTACK :
+ SFMTXRETURN(f, -1);
+ }
+
+ do_continue:
+ for(dc = f->disc; dc; dc = dc->disc)
+ if(dc == disc)
+ break;
+ disc = dc;
+ }
+}
diff --git a/src/lib/libast/sfio/sfread.c b/src/lib/libast/sfio/sfread.c
new file mode 100644
index 0000000..a3aed97
--- /dev/null
+++ b/src/lib/libast/sfio/sfread.c
@@ -0,0 +1,140 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read n bytes from a stream into a buffer
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n)
+#else
+ssize_t sfread(f,buf,n)
+Sfio_t* f; /* read from this stream. */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes to be read. */
+#endif
+{
+ reg uchar *s, *begs;
+ reg ssize_t r;
+ reg int local, justseek;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (ssize_t)(-1));
+
+ GETLOCAL(f,local);
+ justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK;
+
+ if(!buf)
+ SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) );
+
+ /* release peek lock */
+ if(f->mode&SF_PEEK)
+ { if(!(f->mode&SF_READ) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+
+ if(f->mode&SF_GETR)
+ { if(((uchar*)buf + f->val) != f->next &&
+ (!f->rsrv || f->rsrv->data != (uchar*)buf) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+ f->mode &= ~SF_PEEK;
+ SFMTXRETURN(f, 0);
+ }
+ else
+ { if((uchar*)buf != f->next)
+ SFMTXRETURN(f, (ssize_t)(-1));
+ f->mode &= ~SF_PEEK;
+ if(f->mode&SF_PKRD)
+ { /* actually read the data now */
+ f->mode &= ~SF_PKRD;
+ if(n > 0)
+ n = (r = sysreadf(f->file,f->data,n)) < 0 ? 0 : r;
+ f->endb = f->data+n;
+ f->here += n;
+ }
+ f->next += n;
+ f->endr = f->endb;
+ SFMTXRETURN(f, n);
+ }
+ }
+
+ s = begs = (uchar*)buf;
+ for(;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0)
+ { n = s > begs ? s-begs : (size_t)(-1);
+ SFMTXRETURN(f, (ssize_t)n);
+ }
+
+ SFLOCK(f,local);
+
+ if((r = f->endb - f->next) > 0) /* has buffered data */
+ { if(r > (ssize_t)n)
+ r = (ssize_t)n;
+ if(s != f->next)
+ memcpy(s, f->next, r);
+ f->next += r;
+ s += r;
+ n -= r;
+ }
+
+ if(n <= 0) /* all done */
+ break;
+
+ if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) )
+ { f->next = f->endb = f->data;
+
+ /* exact IO is desirable for these cases */
+ if(SFDIRECT(f,n) ||
+ ((f->flags&SF_SHARE) && f->extent < 0) )
+ r = (ssize_t)n;
+ else if(justseek && n <= f->iosz && f->iosz <= f->size)
+ r = f->iosz; /* limit buffering */
+ else r = f->size; /* full buffering */
+
+ /* if read almost full size, then just do it direct */
+ if(r > (ssize_t)n && (r - r/8) <= (ssize_t)n)
+ r = (ssize_t)n;
+
+ /* read directly to user's buffer */
+ if(r == (ssize_t)n && (r = SFRD(f,s,r,f->disc)) >= 0)
+ { s += r;
+ n -= r;
+ if(r == 0 || n == 0) /* eof or eob */
+ break;
+ }
+ else goto do_filbuf;
+ }
+ else
+ { do_filbuf:
+ if(justseek)
+ f->bits |= SF_JUSTSEEK;
+ if(SFFILBUF(f,-1) <= 0)
+ break;
+ }
+ }
+
+ SFOPEN(f,local);
+ r = s-begs;
+ SFMTXRETURN(f, r);
+}
diff --git a/src/lib/libast/sfio/sfreserve.c b/src/lib/libast/sfio/sfreserve.c
new file mode 100644
index 0000000..29772a2
--- /dev/null
+++ b/src/lib/libast/sfio/sfreserve.c
@@ -0,0 +1,210 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Reserve a segment of data or buffer.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Void_t* sfreserve(Sfio_t* f, ssize_t size, int type)
+#else
+Void_t* sfreserve(f,size,type)
+Sfio_t* f; /* file to peek */
+ssize_t size; /* size of peek */
+int type; /* LOCKR: lock stream, LASTR: last record */
+#endif
+{
+ reg ssize_t n, now, sz, iosz;
+ reg Sfrsrv_t* rsrv;
+ reg Void_t* data;
+ reg int mode, local;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,NIL(Void_t*));
+
+ sz = size < 0 ? -size : size;
+
+ /* see if we need to bias toward SF_WRITE instead of the default SF_READ */
+ if(type < 0)
+ mode = 0;
+ else if((mode = type&SF_WRITE) )
+ type &= ~SF_WRITE;
+
+ /* return the last record */
+ if(type == SF_LASTR )
+ { if((n = f->endb - f->next) > 0 && n == f->val )
+ { data = (Void_t*)f->next;
+ f->next += n;
+ }
+ else if((rsrv = f->rsrv) && (n = -rsrv->slen) > 0)
+ { rsrv->slen = 0;
+ _Sfi = f->val = n;
+ data = (Void_t*)rsrv->data;
+ }
+ else
+ { _Sfi = f->val = -1;
+ data = NIL(Void_t*);
+ }
+
+ SFMTXRETURN(f, data);
+ }
+
+ if(type > 0)
+ { if(type == 1 ) /* upward compatibility mode */
+ type = SF_LOCKR;
+ else if(type != SF_LOCKR)
+ SFMTXRETURN(f, NIL(Void_t*));
+ }
+
+ if(size == 0 && (type < 0 || type == SF_LOCKR) )
+ { if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ SFLOCK(f,0);
+ if((n = f->endb - f->next) < 0)
+ n = 0;
+
+ goto done;
+ }
+
+ /* iterate until get to a stream that has data or buffer space */
+ for(local = 0;; local = SF_LOCAL)
+ { _Sfi = f->val = -1;
+
+ if(!mode && !(mode = f->flags&SF_READ) )
+ mode = SF_WRITE;
+ if((int)f->mode != mode && _sfmode(f,mode,local) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, NIL(Void_t*));
+ }
+
+ SFLOCK(f,local);
+
+ if((n = now = f->endb - f->next) < 0)
+ n = 0;
+ if(n > 0 && n >= sz) /* all done */
+ break;
+
+ /* set amount to perform IO */
+ if(size == 0 || (f->mode&SF_WRITE))
+ iosz = -1;
+ else if(size < 0 && n == 0 && f->push) /* maybe stack-pop */
+ { if((iosz = f->push->endb - f->push->next) == 0)
+ iosz = f->push->size;
+ if(iosz < sz)
+ iosz = sz; /* so only get what is asked for */
+ }
+ else
+ { iosz = sz - n; /* get enough to fulfill requirement */
+ if(size < 0 && iosz < (f->size - n) )
+ iosz = f->size - n; /* get as much as possible */
+ if(iosz <= 0) /* nothing to do */
+ break;
+ }
+
+ /* do a buffer refill or flush */
+ now = n;
+ if(f->mode&SF_WRITE)
+ (void)SFFLSBUF(f, iosz);
+ else if(type == SF_LOCKR && f->extent < 0 && (f->flags&SF_SHARE) )
+ { if(n == 0) /* peek-read only if there is no buffered data */
+ { f->mode |= SF_RV;
+ (void)SFFILBUF(f, iosz );
+ }
+ if((n = f->endb - f->next) < sz)
+ { if(f->mode&SF_PKRD)
+ { f->endb = f->endr = f->next;
+ f->mode &= ~SF_PKRD;
+ }
+ break;
+ }
+ }
+ else
+ { /* sfreserve(f,0,0) == sfread(f, sfreserve(f,-1,SF_LOCKR), 0) */
+ if(size == 0 && type == 0)
+ f->mode |= SF_RV;
+
+ (void)SFFILBUF(f, iosz );
+ }
+
+ if((n = f->endb - f->next) <= 0)
+ n = 0;
+
+ if(n >= sz) /* got it */
+ break;
+
+ if(n == now || sferror(f) || sfeof(f)) /* no progress */
+ break;
+
+ /* request was only to assess data availability */
+ if(type == SF_LOCKR && size > 0 && n > 0 )
+ break;
+ }
+
+done: /* compute the buffer to be returned */
+ data = NIL(Void_t*);
+ if(size == 0 || n == 0)
+ { if(n > 0) /* got data */
+ data = (Void_t*)f->next;
+ else if(type == SF_LOCKR && size == 0 && (rsrv = _sfrsrv(f,0)) )
+ data = (Void_t*)rsrv->data;
+ }
+ else if(n >= sz) /* got data */
+ data = (Void_t*)f->next;
+ else if(f->flags&SF_STRING) /* try extending string buffer */
+ { if((f->mode&SF_WRITE) && (f->flags&SF_MALLOC) )
+ { (void)SFWR(f,f->next,sz,f->disc);
+ if((n = f->endb - f->next) >= sz )
+ data = (Void_t*)f->next;
+ }
+ }
+ else if(f->mode&SF_WRITE) /* allocate side buffer */
+ { if(type == SF_LOCKR && (rsrv = _sfrsrv(f, sz)) )
+ data = (Void_t*)rsrv->data;
+ }
+ else if(type != SF_LOCKR && sz > f->size && (rsrv = _sfrsrv(f,sz)) )
+ { if((n = SFREAD(f,(Void_t*)rsrv->data,sz)) >= sz) /* read side buffer */
+ data = (Void_t*)rsrv->data;
+ else rsrv->slen = -n;
+ }
+
+ SFOPEN(f,0);
+
+ if(data)
+ { if(type == SF_LOCKR)
+ { f->mode |= SF_PEEK;
+ if((f->mode & SF_READ) && size == 0 && data != f->next)
+ f->mode |= SF_GETR; /* so sfread() will unlock */
+ f->endr = f->endw = f->data;
+ }
+ else
+ { if(data == (Void_t*)f->next)
+ f->next += (size >= 0 ? size : n);
+ }
+ }
+
+ _Sfi = f->val = n; /* return true buffer size */
+
+ SFMTXRETURN(f, data);
+}
diff --git a/src/lib/libast/sfio/sfresize.c b/src/lib/libast/sfio/sfresize.c
new file mode 100644
index 0000000..ae5c83c
--- /dev/null
+++ b/src/lib/libast/sfio/sfresize.c
@@ -0,0 +1,83 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Resize a stream.
+ Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfresize(Sfio_t* f, Sfoff_t size)
+#else
+int sfresize(f, size)
+Sfio_t* f;
+Sfoff_t size;
+#endif
+{
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(size < 0 || f->extent < 0 ||
+ (f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) )
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,0);
+
+ if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+
+ if(f->extent >= size)
+ { if((f->flags&SF_MALLOC) && (f->next - f->data) <= size)
+ { size_t s = (((size_t)size + 1023)/1024)*1024;
+ Void_t* d;
+ if(s < f->size && (d = realloc(f->data, s)) )
+ { f->data = d;
+ f->size = s;
+ f->extent = s;
+ }
+ }
+ memclear((char*)(f->data+size), (int)(f->extent-size));
+ }
+ else
+ { if(SFSK(f, size, SEEK_SET, f->disc) != size)
+ SFMTXRETURN(f, -1);
+ memclear((char*)(f->data+f->extent), (int)(size-f->extent));
+ }
+ }
+ else
+ { if(f->next > f->data)
+ SFSYNC(f);
+#if _lib_ftruncate
+ if(ftruncate(f->file, (sfoff_t)size) < 0)
+ SFMTXRETURN(f, -1);
+#else
+ SFMTXRETURN(f, -1);
+#endif
+ }
+
+ f->extent = size;
+
+ SFOPEN(f, 0);
+
+ SFMTXRETURN(f, 0);
+}
diff --git a/src/lib/libast/sfio/sfscanf.c b/src/lib/libast/sfio/sfscanf.c
new file mode 100644
index 0000000..12eec1a
--- /dev/null
+++ b/src/lib/libast/sfio/sfscanf.c
@@ -0,0 +1,102 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read formated data from a stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfscanf(Sfio_t* f, const char* form, ...)
+#else
+int sfscanf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ reg int rv;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ reg Sfio_t* f;
+ reg char* form;
+ va_start(args);
+ f = va_arg(args,Sfio_t*);
+ form = va_arg(args,char*);
+#endif
+
+ rv = (f && form) ? sfvscanf(f,form,args) : -1;
+ va_end(args);
+ return rv;
+}
+
+#if __STD_C
+int sfvsscanf(const char* s, const char* form, va_list args)
+#else
+int sfvsscanf(s, form, args)
+char* s;
+char* form;
+va_list args;
+#endif
+{
+ Sfio_t f;
+
+ if(!s || !form)
+ return -1;
+
+ /* make a fake stream */
+ SFCLEAR(&f,NIL(Vtmutex_t*));
+ f.flags = SF_STRING|SF_READ;
+ f.bits = SF_PRIVATE;
+ f.mode = SF_READ;
+ f.size = strlen((char*)s);
+ f.data = f.next = f.endw = (uchar*)s;
+ f.endb = f.endr = f.data+f.size;
+
+ return sfvscanf(&f,form,args);
+}
+
+#if __STD_C
+int sfsscanf(const char* s, const char* form,...)
+#else
+int sfsscanf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ reg int rv;
+#if __STD_C
+ va_start(args,form);
+#else
+ reg char* s;
+ reg char* form;
+ va_start(args);
+ s = va_arg(args,char*);
+ form = va_arg(args,char*);
+#endif
+
+ rv = (s && form) ? sfvsscanf(s,form,args) : -1;
+ va_end(args);
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfseek.c b/src/lib/libast/sfio/sfseek.c
new file mode 100644
index 0000000..1f446ba
--- /dev/null
+++ b/src/lib/libast/sfio/sfseek.c
@@ -0,0 +1,281 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Set the IO pointer to a specific location in the stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static void newpos(Sfio_t* f, Sfoff_t p)
+#else
+static void newpos(f, p)
+Sfio_t* f;
+Sfoff_t p;
+#endif
+{
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f, f->data, f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endr = f->endw = f->data;
+ f->endb = (f->mode&SF_WRITE) ? f->data+f->size : f->data;
+ if((f->here = p) < 0)
+ { f->extent = -1;
+ f->here = 0;
+ }
+}
+
+#if __STD_C
+Sfoff_t sfseek(Sfio_t* f, Sfoff_t p, int type)
+#else
+Sfoff_t sfseek(f,p,type)
+Sfio_t* f; /* seek to a new location in this stream */
+Sfoff_t p; /* place to seek to */
+int type; /* 0: from org, 1: from here, 2: from end */
+#endif
+{
+ Sfoff_t r, s;
+ int mode, local, hardseek, mustsync;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ GETLOCAL(f,local);
+
+ hardseek = (type|f->flags)&(SF_SHARE|SF_PUBLIC);
+
+ if(hardseek && f->mode == (SF_READ|SF_SYNCED) )
+ { newpos(f,f->here);
+ f->mode = SF_READ;
+ }
+
+ /* set and initialize the stream to a definite mode */
+ if((int)SFMODE(f,local) != (mode = f->mode&SF_RDWR))
+ { int flags = f->flags;
+
+ if(hardseek&SF_PUBLIC) /* seek ptr must follow file descriptor */
+ f->flags |= SF_SHARE|SF_PUBLIC;
+ mode = _sfmode(f,mode,local);
+ if(hardseek&SF_PUBLIC)
+ f->flags = flags;
+
+ if(mode < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ mustsync = (type&SF_SHARE) && !(type&SF_PUBLIC) &&
+ (f->mode&SF_READ) && !(f->flags&SF_STRING);
+
+ /* Xopen-compliant */
+ if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) != SEEK_SET &&
+ type != SEEK_CUR && type != SEEK_END )
+ { errno = EINVAL;
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ if(f->extent < 0)
+ { /* let system call set errno */
+ (void)SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ /* throw away ungetc data */
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ /* lock the stream for internal manipulations */
+ SFLOCK(f,local);
+
+ /* clear error and eof bits */
+ f->flags &= ~(SF_EOF|SF_ERROR);
+
+ while(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+
+ if(type == SEEK_CUR)
+ r = p + (f->next - f->data);
+ else if(type == SEEK_END)
+ r = p + f->extent;
+ else r = p;
+
+ if(r >= 0 && r <= f->size)
+ { p = r;
+ f->next = f->data+p;
+ f->here = p;
+ if(p > f->extent)
+ memclear((char*)(f->data+f->extent),(int)(p-f->extent));
+ goto done;
+ }
+
+ /* check exception handler, note that this may pop stream */
+ if(SFSK(f,r,SEEK_SET,f->disc) != r)
+ { p = -1;
+ goto done;
+ }
+ else if(!(f->flags&SF_STRING))
+ { p = r;
+ goto done;
+ }
+ }
+
+ if(f->mode&SF_WRITE)
+ { /* see if we can avoid flushing buffer */
+ if(!hardseek && type < SEEK_END && !(f->flags&SF_APPENDWR) )
+ { s = f->here + (f->next - f->data);
+ r = p + (type == SEEK_SET ? 0 : s);
+ if(r == s)
+ { p = r;
+ goto done;
+ }
+ }
+
+ if(f->next > f->data && SFSYNC(f) < 0)
+ { p = -1;
+ goto done;
+ }
+ }
+
+ if(type == SEEK_END || (f->mode&SF_WRITE) )
+ { if((hardseek&SF_PUBLIC) || type == SEEK_END)
+ p = SFSK(f, p, type, f->disc);
+ else
+ { r = p + (type == SEEK_CUR ? f->here : 0);
+ p = (hardseek || r != f->here) ? SFSK(f,r,SEEK_SET,f->disc) : r;
+ }
+ if(p >= 0)
+ newpos(f,p);
+
+ goto done;
+ }
+
+ /* if get here, must be a read stream */
+ s = f->here - (f->endb - f->next);
+ r = p + (type == SEEK_CUR ? s : 0);
+ if(r <= f->here && r >= (f->here - (f->endb-f->data)) )
+ { if((hardseek || (type == SEEK_CUR && p == 0)) )
+ { if((s = SFSK(f, (Sfoff_t)0, SEEK_CUR, f->disc)) == f->here ||
+ (s >= 0 && !(hardseek&SF_PUBLIC) &&
+ (s = SFSK(f, f->here, SEEK_SET, f->disc)) == f->here) )
+ goto near_done;
+ else if(s < 0)
+ { p = -1;
+ goto done;
+ }
+ else
+ { newpos(f,s);
+ hardseek = 0;
+ }
+ }
+ else
+ { near_done:
+ f->next = f->endb - (f->here - r);
+ p = r;
+ goto done;
+ }
+ }
+
+ /* desired position */
+ if((p += type == SEEK_CUR ? s : 0) < 0)
+ goto done;
+
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { /* if mmap is not great, stop mmaping if moving around too much */
+#if _mmap_worthy < 2
+ if((f->next - f->data) < ((f->endb - f->data)/4) )
+ { SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+ hardseek = 1; /* this forces a hard seek below */
+ }
+ else
+#endif
+ { /* for mmap, f->here can be virtual except for hardseek */
+ newpos(f,p);
+ if(!hardseek)
+ goto done;
+ }
+ }
+#endif
+
+ if(f->endb > f->next)
+ { /* reduce wastage in future buffer fillings */
+ f->iosz = (f->next - f->data) + (f->endb - f->next)/2;
+ f->iosz = ((f->iosz + f->blksz-1)/f->blksz)*f->blksz;
+ }
+ if(f->iosz >= f->size)
+ f->iosz = 0;
+
+ /* buffer is now considered empty */
+ f->next = f->endr = f->endb = f->data;
+
+ /* small backseeks often come in bunches, so seek back as far as possible */
+ if(p < f->lpos && f->size > f->blksz && (p + f->blksz) > s)
+ { if((r = s - f->size) < 0)
+ r = 0;
+ }
+ /* try to align buffer to block boundary to enhance I/O speed */
+ else if(f->blksz > 0 && f->size >= 2*f->blksz)
+ r = p - (p%f->blksz);
+ else
+ { r = p;
+
+ /* seeking around and wasting data, be conservative */
+ if(f->iosz > 0 && (p > f->lpos || p < f->lpos-f->size) )
+ f->bits |= SF_JUSTSEEK;
+ }
+
+ if((hardseek || r != f->here) && (f->here = SFSK(f,r,SEEK_SET,f->disc)) != r)
+ { if(r < p) /* now try to just get to p */
+ f->here = SFSK(f,p,SEEK_SET,f->disc);
+ if(f->here != p)
+ p = -1;
+ goto done;
+ }
+
+ if(r < p) /* read to cover p */
+ { (void)SFRD(f, f->data, f->size, f->disc);
+ if(p <= f->here && p >= (f->here - (f->endb - f->data)) )
+ f->next = f->endb - (size_t)(f->here-p);
+ else /* recover from read failure by just seeking to p */
+ { f->next = f->endb = f->data;
+ if((f->here = SFSK(f,p,SEEK_SET,f->disc)) != p)
+ p = -1;
+ }
+ }
+
+done :
+ if(f->here < 0) /* hasn't been the best of time */
+ { f->extent = -1;
+ f->here = 0;
+ }
+
+ f->lpos = p;
+
+ SFOPEN(f,local);
+
+ if(mustsync)
+ sfsync(f);
+ SFMTXRETURN(f, p);
+}
diff --git a/src/lib/libast/sfio/sfset.c b/src/lib/libast/sfio/sfset.c
new file mode 100644
index 0000000..a18662e
--- /dev/null
+++ b/src/lib/libast/sfio/sfset.c
@@ -0,0 +1,99 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Set some control flags or file descript for the stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfset(Sfio_t* f, int flags, int set)
+#else
+int sfset(f,flags,set)
+Sfio_t* f;
+int flags;
+int set;
+#endif
+{
+ reg int oflags, tflags, rv;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,0);
+
+ if(flags == 0 && set == 0)
+ SFMTXRETURN(f, (f->flags&SF_FLAGS));
+
+ if((oflags = (f->mode&SF_RDWR)) != (int)f->mode)
+ { /* avoid sfsetbuf() isatty() call if user sets (SF_LINE|SF_WCWIDTH) */
+ if(set && (flags & (SF_LINE|SF_WCWIDTH)) && !(f->flags & (SF_LINE|SF_WCWIDTH)))
+ { tflags = (SF_LINE|SF_WCWIDTH);
+ f->flags |= tflags;
+ }
+ else tflags = 0;
+ rv = _sfmode(f,oflags,0);
+ if(tflags)
+ f->flags &= ~tflags;
+ if(rv < 0)
+ SFMTXRETURN(f, 0);
+ }
+ if(flags == 0)
+ SFMTXRETURN(f, (f->flags&SF_FLAGS));
+
+ SFLOCK(f,0);
+
+ /* preserve at least one rd/wr flag */
+ oflags = f->flags;
+ if(!(f->bits&SF_BOTH) || (flags&SF_RDWR) == SF_RDWR )
+ flags &= ~SF_RDWR;
+
+ /* set the flag */
+ if(set)
+ f->flags |= (flags&SF_SETS);
+ else f->flags &= ~(flags&SF_SETS);
+
+ /* must have at least one of read/write */
+ if(!(f->flags&SF_RDWR))
+ f->flags |= (oflags&SF_RDWR);
+
+ if(f->extent < 0)
+ f->flags &= ~SF_APPENDWR;
+
+ /* turn to appropriate mode as necessary */
+ if((flags &= SF_RDWR) )
+ { if(!set)
+ { if(flags == SF_READ)
+ flags = SF_WRITE;
+ else flags = SF_READ;
+ }
+ if((flags == SF_WRITE && !(f->mode&SF_WRITE)) ||
+ (flags == SF_READ && !(f->mode&(SF_READ|SF_SYNCED))) )
+ (void)_sfmode(f,flags,1);
+ }
+
+ /* if not shared or unseekable, public means nothing */
+ if(!(f->flags&SF_SHARE) || f->extent < 0)
+ f->flags &= ~SF_PUBLIC;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, (oflags&SF_FLAGS));
+}
diff --git a/src/lib/libast/sfio/sfsetbuf.c b/src/lib/libast/sfio/sfsetbuf.c
new file mode 100644
index 0000000..cb0240b
--- /dev/null
+++ b/src/lib/libast/sfio/sfsetbuf.c
@@ -0,0 +1,426 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getpagesize
+#else
+#define getpagesize ______getpagesize
+#endif
+
+#include "sfhdr.h"
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getpagesize
+#else
+#undef getpagesize
+#endif
+
+#if _lib_getpagesize
+_BEGIN_EXTERNS_
+extern int getpagesize _ARG_((void));
+_END_EXTERNS_
+#endif
+
+/* Set a (new) buffer for a stream.
+** If size < 0, it is assigned a suitable value depending on the
+** kind of stream. The actual buffer size allocated is dependent
+** on how much memory is available.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if !_sys_stat
+struct stat
+{ int st_mode;
+ int st_size;
+};
+#undef sysfstatf
+#define sysfstatf(fd,st) (-1)
+#endif /*_sys_stat*/
+
+#if _PACKAGE_ast && !defined(SFSETLINEMODE)
+#define SFSETLINEMODE 1
+#endif
+
+#if SFSETLINEMODE
+
+static int sfsetlinemode()
+{ char* astsfio;
+ char* endw;
+
+ static int modes = -1;
+ static const char sf_line[] = "SF_LINE";
+ static const char sf_maxr[] = "SF_MAXR=";
+ static const char sf_wcwidth[] = "SF_WCWIDTH";
+
+#define ISSEPAR(c) ((c) == ',' || (c) == ' ' || (c) == '\t')
+ if (modes < 0)
+ { modes = 0;
+ if(astsfio = getenv("SFIO_OPTIONS"))
+ { for(; *astsfio != 0; astsfio = endw)
+ { while(ISSEPAR(*astsfio) )
+ ++astsfio;
+ for(endw = astsfio; *endw && !ISSEPAR(*endw); ++endw)
+ ;
+ if((endw-astsfio) > (sizeof(sf_line)-1) &&
+ strncmp(astsfio,sf_line,sizeof(sf_line)-1) == 0)
+ modes |= SF_LINE;
+ else if((endw-astsfio) > (sizeof(sf_maxr)-1) &&
+ strncmp(astsfio,sf_maxr,sizeof(sf_maxr)-1) == 0)
+#if _PACKAGE_ast
+ _Sfmaxr = (ssize_t)strtonll(astsfio+sizeof(sf_maxr)-1,NiL,NiL,0);
+#else
+ _Sfmaxr = (ssize_t)strtol(astsfio+sizeof(sf_maxr)-1,NiL,0);
+#endif
+ else if((endw-astsfio) > (sizeof(sf_wcwidth)-1) &&
+ strncmp(astsfio,sf_wcwidth,sizeof(sf_wcwidth)-1) == 0)
+ modes |= SF_WCWIDTH;
+ }
+ }
+ }
+ return modes;
+}
+
+#endif
+
+#if __STD_C
+Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)
+#else
+Void_t* sfsetbuf(f,buf,size)
+Sfio_t* f; /* stream to be buffered */
+Void_t* buf; /* new buffer */
+size_t size; /* buffer size, -1 for default size */
+#endif
+{
+ int sf_malloc, oflags, init, okmmap, local;
+ ssize_t bufsize, blksz;
+ Sfdisc_t* disc;
+ sfstat_t st;
+ uchar* obuf = NIL(uchar*);
+ ssize_t osize = 0;
+ SFMTXDECL(f);
+
+ SFONCE();
+
+ SFMTXENTER(f,NIL(Void_t*));
+
+ GETLOCAL(f,local);
+
+ if(size == 0 && buf)
+ { /* special case to get buffer info */
+ _Sfi = f->val = (f->bits&SF_MMAP) ? (f->endb-f->data) : f->size;
+ SFMTXRETURN(f, (Void_t*)f->data);
+ }
+
+ /* cleanup actions already done, don't allow write buffering any more */
+ if(_Sfexiting && !(f->flags&SF_STRING) && (f->mode&SF_WRITE))
+ { buf = NIL(Void_t*);
+ size = 0;
+ }
+
+ if((init = f->mode&SF_INIT) )
+ { if(!f->pool && _sfsetpool(f) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+ }
+ else if((f->mode&SF_RDWR) != SFMODE(f,local) && _sfmode(f,0,local) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ if(init)
+ f->mode = (f->mode&SF_RDWR)|SF_LOCK;
+ else
+ { int rv;
+
+ /* make sure there is no hidden read data */
+ if(f->proc && (f->flags&SF_READ) && (f->mode&SF_WRITE) &&
+ _sfmode(f,SF_READ,local) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ /* synchronize first */
+ SFLOCK(f,local); rv = SFSYNC(f); SFOPEN(f,local);
+ if(rv < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ /* turn off the SF_SYNCED bit because buffer is changing */
+ f->mode &= ~SF_SYNCED;
+ }
+
+ SFLOCK(f,local);
+
+ if((Sfio_t*)buf != f)
+ blksz = -1;
+ else /* setting alignment size only */
+ { blksz = (ssize_t)size;
+
+ if(!init) /* stream already initialized */
+ { obuf = f->data;
+ osize = f->size;
+ goto done;
+ }
+ else /* initialize stream as if in the default case */
+ { buf = NIL(Void_t*);
+ size = (size_t)SF_UNBOUND;
+ }
+ }
+
+ bufsize = 0;
+ oflags = f->flags;
+
+ /* see if memory mapping is possible (see sfwrite for SF_BOTH) */
+ okmmap = (buf || (f->flags&SF_STRING) || (f->flags&SF_RDWR) == SF_RDWR) ? 0 : 1;
+
+ /* save old buffer info */
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { if(f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+ } else
+#endif
+ if(f->data == f->tiny)
+ { f->data = NIL(uchar*);
+ f->size = 0;
+ }
+ obuf = f->data;
+ osize = f->size;
+
+ f->flags &= ~SF_MALLOC;
+ f->bits &= ~SF_MMAP;
+
+ /* pure read/string streams must have a valid string */
+ if((f->flags&(SF_RDWR|SF_STRING)) == SF_RDSTR &&
+ (size == (size_t)SF_UNBOUND || !buf))
+ size = 0;
+
+ /* set disc to the first discipline with a seekf */
+ for(disc = f->disc; disc; disc = disc->disc)
+ if(disc->seekf)
+ break;
+
+ if((init || local) && !(f->flags&SF_STRING))
+ { /* ASSERT(f->file >= 0) */
+ st.st_mode = 0;
+
+ /* if has discipline, set size by discipline if possible */
+ if(!_sys_stat || disc)
+ { if((f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc)) < 0)
+ goto unseekable;
+ else
+ { Sfoff_t e;
+ if((e = SFSK(f,(Sfoff_t)0,SEEK_END,disc)) >= 0)
+ f->extent = e > f->here ? e : f->here;
+ (void)SFSK(f,f->here,SEEK_SET,disc);
+ goto setbuf;
+ }
+ }
+
+ /* get file descriptor status */
+ if(sysfstatf((int)f->file,&st) < 0)
+ f->here = -1;
+ else
+ {
+#if _sys_stat && _stat_blksize /* preferred io block size */
+ f->blksz = (size_t)st.st_blksize;
+#endif
+ bufsize = 64 * 1024;
+ if(S_ISDIR(st.st_mode) || (Sfoff_t)st.st_size < (Sfoff_t)SF_GRAIN)
+ okmmap = 0;
+ if(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
+ else f->here = -1;
+
+#if O_TEXT /* no memory mapping with O_TEXT because read()/write() alter data stream */
+ if(okmmap && f->here >= 0 &&
+ (sysfcntlf((int)f->file,F_GETFL,0) & O_TEXT) )
+ okmmap = 0;
+#endif
+ }
+
+#if SFSETLINEMODE
+ if(init)
+ f->flags |= sfsetlinemode();
+#endif
+
+ if(f->here >= 0)
+ { f->extent = (Sfoff_t)st.st_size;
+
+ /* seekable std-devices are share-public by default */
+ if(f == sfstdin || f == sfstdout || f == sfstderr)
+ f->flags |= SF_SHARE|SF_PUBLIC;
+ }
+ else
+ {
+ unseekable:
+ f->extent = -1;
+ f->here = 0;
+
+ if(init)
+ { if(S_ISCHR(st.st_mode) )
+ { int oerrno = errno;
+
+ bufsize = SF_GRAIN;
+
+ /* set line mode for terminals */
+ if(!(f->flags&(SF_LINE|SF_WCWIDTH)) && isatty(f->file))
+ f->flags |= SF_LINE|SF_WCWIDTH;
+#if _sys_stat
+ else /* special case /dev/null */
+ { reg int dev, ino;
+ static int null_checked, null_dev, null_ino;
+ dev = (int)st.st_dev;
+ ino = (int)st.st_ino;
+ if(!null_checked)
+ { if(sysstatf(DEVNULL,&st) < 0)
+ null_checked = -1;
+ else
+ { null_checked = 1;
+ null_dev = (int)st.st_dev;
+ null_ino = (int)st.st_ino;
+ }
+ }
+ if(null_checked >= 0 && dev == null_dev && ino == null_ino)
+ SFSETNULL(f);
+ }
+#endif
+ errno = oerrno;
+ }
+
+ /* initialize side buffer for r+w unseekable streams */
+ if(!f->proc && (f->bits&SF_BOTH) )
+ (void)_sfpopen(f,-1,-1,1);
+ }
+ }
+
+ /* set page size, this is also the desired default buffer size */
+ if(_Sfpage <= 0)
+ {
+#if _lib_getpagesize
+ if((_Sfpage = (size_t)getpagesize()) <= 0)
+#endif
+ _Sfpage = SF_PAGE;
+ }
+ }
+
+#ifdef MAP_TYPE
+ if(okmmap && size && (f->mode&SF_READ) && f->extent >= 0 )
+ { /* see if we can try memory mapping */
+ if(!disc)
+ for(disc = f->disc; disc; disc = disc->disc)
+ if(disc->readf)
+ break;
+ if(!disc)
+ { f->bits |= SF_MMAP;
+ if(size == (size_t)SF_UNBOUND)
+ { if(bufsize > _Sfpage)
+ size = bufsize * SF_NMAP;
+ else size = _Sfpage * SF_NMAP;
+ if(size > 256*1024)
+ size = 256*1024;
+ }
+ }
+ }
+#endif
+
+ /* get buffer space */
+setbuf:
+ if(size == (size_t)SF_UNBOUND)
+ { /* define a default size suitable for block transfer */
+ if(init && osize > 0)
+ size = osize;
+ else if(f == sfstderr && (f->mode&SF_WRITE))
+ size = 0;
+ else if(f->flags&SF_STRING )
+ size = SF_GRAIN;
+ else if((f->flags&SF_READ) && !(f->bits&SF_BOTH) &&
+ f->extent > 0 && f->extent < (Sfoff_t)_Sfpage )
+ size = (((size_t)f->extent + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
+ else if((ssize_t)(size = _Sfpage) < bufsize)
+ size = bufsize;
+
+ buf = NIL(Void_t*);
+ }
+
+ sf_malloc = 0;
+ if(size > 0 && !buf && !(f->bits&SF_MMAP))
+ { /* try to allocate a buffer */
+ if(obuf && size == (size_t)osize && init)
+ { buf = (Void_t*)obuf;
+ obuf = NIL(uchar*);
+ sf_malloc = (oflags&SF_MALLOC);
+ }
+ if(!buf)
+ { /* do allocation */
+ while(!buf && size > 0)
+ { if((buf = (Void_t*)malloc(size)) )
+ break;
+ else size /= 2;
+ }
+ if(size > 0)
+ sf_malloc = SF_MALLOC;
+ }
+ }
+
+ if(size == 0 && !(f->flags&SF_STRING) && !(f->bits&SF_MMAP) && (f->mode&SF_READ))
+ { /* use the internal buffer */
+ size = sizeof(f->tiny);
+ buf = (Void_t*)f->tiny;
+ }
+
+ /* set up new buffer */
+ f->size = size;
+ f->next = f->data = f->endr = f->endw = (uchar*)buf;
+ f->endb = (f->mode&SF_READ) ? f->data : f->data+size;
+ if(f->flags&SF_STRING)
+ { /* these fields are used to test actual size - see sfseek() */
+ f->extent = (!sf_malloc &&
+ ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ) ? size : 0;
+ f->here = 0;
+
+ /* read+string stream should have all data available */
+ if((f->mode&SF_READ) && !sf_malloc)
+ f->endb = f->data+size;
+ }
+
+ f->flags = (f->flags & ~SF_MALLOC)|sf_malloc;
+
+ if(obuf && obuf != f->data && osize > 0 && (oflags&SF_MALLOC))
+ { free((Void_t*)obuf);
+ obuf = NIL(uchar*);
+ }
+
+done:
+ _Sfi = f->val = obuf ? osize : 0;
+
+ /* blksz is used for aligning disk block boundary while reading data to
+ ** optimize data transfer from disk (eg, via direct I/O). blksz can be
+ ** at most f->size/2 so that data movement in buffer can be optimized.
+ ** blksz should also be a power-of-2 for optimal disk seeks.
+ */
+ if(blksz <= 0 || (blksz & (blksz-1)) != 0 )
+ blksz = SF_GRAIN;
+ while(blksz > f->size/2)
+ blksz /= 2;
+ f->blksz = blksz;
+
+ SFOPEN(f,local);
+
+ SFMTXRETURN(f, (Void_t*)obuf);
+}
diff --git a/src/lib/libast/sfio/sfsetfd.c b/src/lib/libast/sfio/sfsetfd.c
new file mode 100644
index 0000000..9ca3732
--- /dev/null
+++ b/src/lib/libast/sfio/sfsetfd.c
@@ -0,0 +1,136 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Change the file descriptor
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static int _sfdup(int fd, int newfd)
+#else
+static int _sfdup(fd,newfd)
+int fd;
+int newfd;
+#endif
+{
+ reg int dupfd;
+
+#ifdef F_DUPFD /* the simple case */
+ while((dupfd = sysfcntlf(fd,F_DUPFD,newfd)) < 0 && errno == EINTR)
+ errno = 0;
+ return dupfd;
+
+#else /* do it the hard way */
+ if((dupfd = sysdupf(fd)) < 0 || dupfd >= newfd)
+ return dupfd;
+
+ /* dup() succeeded but didn't get the right number, recurse */
+ newfd = _sfdup(fd,newfd);
+
+ /* close the one that didn't match */
+ CLOSE(dupfd);
+
+ return newfd;
+#endif
+}
+
+#if __STD_C
+int sfsetfd(Sfio_t* f, int newfd)
+#else
+int sfsetfd(f,newfd)
+Sfio_t *f;
+int newfd;
+#endif
+{
+ reg int oldfd;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(f->flags&SF_STRING)
+ SFMTXRETURN(f, -1);
+
+ if((f->mode&SF_INIT) && f->file < 0)
+ { /* restoring file descriptor after a previous freeze */
+ if(newfd < 0)
+ SFMTXRETURN(f, -1);
+ }
+ else
+ { /* change file descriptor */
+ if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ oldfd = f->file;
+ if(oldfd >= 0)
+ { if(newfd >= 0)
+ { if((newfd = _sfdup(oldfd,newfd)) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ }
+ CLOSE(oldfd);
+ }
+ else
+ { /* sync stream if necessary */
+ if(((f->mode&SF_WRITE) && f->next > f->data) ||
+ (f->mode&SF_READ) || f->disc == _Sfudisc)
+ { if(SFSYNC(f) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ }
+ }
+
+ if(((f->mode&SF_WRITE) && f->next > f->data) ||
+ ((f->mode&SF_READ) && f->extent < 0 &&
+ f->next < f->endb) )
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ }
+
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+
+ /* make stream appears uninitialized */
+ f->endb = f->endr = f->endw = f->data;
+ f->extent = f->here = 0;
+ f->mode = (f->mode&SF_RDWR)|SF_INIT;
+ f->bits &= ~SF_NULL; /* off /dev/null handling */
+ }
+ }
+
+ SFOPEN(f,0);
+ }
+
+ /* notify changes */
+ if(_Sfnotify)
+ (*_Sfnotify)(f, SF_SETFD, (void*)((long)newfd));
+
+ f->file = newfd;
+
+ SFMTXRETURN(f,newfd);
+}
diff --git a/src/lib/libast/sfio/sfsize.c b/src/lib/libast/sfio/sfsize.c
new file mode 100644
index 0000000..7b6d4aa
--- /dev/null
+++ b/src/lib/libast/sfio/sfsize.c
@@ -0,0 +1,109 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Get the size of a stream.
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+Sfoff_t sfsize(Sfio_t* f)
+#else
+Sfoff_t sfsize(f)
+Sfio_t* f;
+#endif
+{
+ Sfdisc_t* disc;
+ reg int mode;
+ Sfoff_t s;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+
+ if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+ SFMTXRETURN(f, f->extent);
+ }
+
+ SFLOCK(f,0);
+
+ s = f->here;
+
+ if(f->extent >= 0)
+ { if(f->flags&(SF_SHARE|SF_APPENDWR))
+ { for(disc = f->disc; disc; disc = disc->disc)
+ if(disc->seekf)
+ break;
+ if(!_sys_stat || disc)
+ { Sfoff_t e;
+ if((e = SFSK(f,0,SEEK_END,disc)) >= 0)
+ f->extent = e;
+ if(SFSK(f,f->here,SEEK_SET,disc) != f->here)
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc);
+ }
+#if _sys_stat
+ else
+ { sfstat_t st;
+ if(sysfstatf(f->file,&st) < 0)
+ f->extent = -1;
+ else if((f->extent = st.st_size) < f->here)
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc);
+ }
+#endif
+ }
+
+ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC))
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
+ }
+
+ if(f->here != s && (f->mode&SF_READ) )
+ { /* buffered data is known to be invalid */
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endb = f->endr = f->endw = f->data;
+ }
+
+ if(f->here < 0)
+ f->extent = -1;
+ else if(f->extent < f->here)
+ f->extent = f->here;
+
+ if((s = f->extent) >= 0)
+ { if(f->flags&SF_APPENDWR)
+ s += (f->next - f->data);
+ else if(f->mode&SF_WRITE)
+ { s = f->here + (f->next - f->data);
+ if(s < f->extent)
+ s = f->extent;
+ }
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, s);
+}
diff --git a/src/lib/libast/sfio/sfsk.c b/src/lib/libast/sfio/sfsk.c
new file mode 100644
index 0000000..4b82a4d
--- /dev/null
+++ b/src/lib/libast/sfio/sfsk.c
@@ -0,0 +1,106 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Seek function that knows discipline
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+Sfoff_t sfsk(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
+#else
+Sfoff_t sfsk(f,addr,type,disc)
+Sfio_t* f;
+Sfoff_t addr;
+int type;
+Sfdisc_t* disc;
+#endif
+{
+ Sfoff_t p;
+ reg Sfdisc_t* dc;
+ reg ssize_t s;
+ reg int local, mode;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ GETLOCAL(f,local);
+ if(!local && !(f->bits&SF_DCDOWN))
+ { if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ if(SFSYNC(f) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+#ifdef MAP_TYPE
+ if(f->mode == SF_READ && (f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f, f->data, f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endb = f->endr = f->endw = f->data;
+ }
+
+ if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) > SEEK_END)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+
+ for(;;)
+ { dc = disc;
+ if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+ if(type == SEEK_SET)
+ s = (ssize_t)addr;
+ else if(type == SEEK_CUR)
+ s = (ssize_t)(addr + f->here);
+ else s = (ssize_t)(addr + f->extent);
+ }
+ else
+ { SFDISC(f,dc,seekf);
+ if(dc && dc->seekf)
+ { SFDCSK(f,addr,type,dc,p);
+ }
+ else
+ { p = syslseekf(f->file,(sfoff_t)addr,type);
+ }
+ if(p >= 0)
+ SFMTXRETURN(f,p);
+ s = -1;
+ }
+
+ if(local)
+ SETLOCAL(f);
+ switch(_sfexcept(f,SF_SEEK,s,dc))
+ {
+ case SF_EDISC:
+ case SF_ECONT:
+ if(f->flags&SF_STRING)
+ SFMTXRETURN(f, (Sfoff_t)s);
+ goto do_continue;
+ default:
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ do_continue:
+ for(dc = f->disc; dc; dc = dc->disc)
+ if(dc == disc)
+ break;
+ disc = dc;
+ }
+}
diff --git a/src/lib/libast/sfio/sfstack.c b/src/lib/libast/sfio/sfstack.c
new file mode 100644
index 0000000..bc2ab13
--- /dev/null
+++ b/src/lib/libast/sfio/sfstack.c
@@ -0,0 +1,115 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+
+/* Push/pop streams
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define STKMTXLOCK(f1,f2) \
+ { if(f1) SFMTXLOCK(f1); \
+ if(f2) SFMTXLOCK(f2); \
+ }
+#define STKMTXRETURN(f1,f2,rv) \
+ { if(f1) SFMTXUNLOCK(f1); \
+ if(f2) SFMTXUNLOCK(f2); \
+ return(rv); \
+ }
+
+#if __STD_C
+Sfio_t* sfstack(Sfio_t* f1, Sfio_t* f2)
+#else
+Sfio_t* sfstack(f1,f2)
+Sfio_t* f1; /* base of stack */
+Sfio_t* f2; /* top of stack */
+#endif
+{
+ reg int n;
+ reg Sfio_t* rf;
+ reg Sfrsrv_t* rsrv;
+ reg Void_t* mtx;
+
+ STKMTXLOCK(f1,f2);
+
+ if(f1 && (f1->mode&SF_RDWR) != f1->mode && _sfmode(f1,0,0) < 0)
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ if(f2 && (f2->mode&SF_RDWR) != f2->mode && _sfmode(f2,0,0) < 0)
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ if(!f1)
+ STKMTXRETURN(f1,f2, f2);
+
+ /* give access to other internal functions */
+ _Sfstack = sfstack;
+
+ if(f2 == SF_POPSTACK)
+ { if(!(f2 = f1->push))
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ f2->mode &= ~SF_PUSH;
+ }
+ else
+ { if(f2->push)
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ if(f1->pool && f1->pool != &_Sfpool && f1->pool != f2->pool &&
+ f1 == f1->pool->sf[0])
+ { /* get something else to pool front since f1 will be locked */
+ for(n = 1; n < f1->pool->n_sf; ++n)
+ { if(SFFROZEN(f1->pool->sf[n]) )
+ continue;
+ (*_Sfpmove)(f1->pool->sf[n],0);
+ break;
+ }
+ }
+ }
+
+ if(f2->pool && f2->pool != &_Sfpool && f2 != f2->pool->sf[0])
+ (*_Sfpmove)(f2,0);
+
+ /* swap streams */
+ sfswap(f1,f2);
+
+ /* but the reserved buffer and mutex must remain the same */
+ rsrv = f1->rsrv; f1->rsrv = f2->rsrv; f2->rsrv = rsrv;
+ mtx = f1->mutex; f1->mutex = f2->mutex; f2->mutex = mtx;
+
+ SFLOCK(f1,0);
+ SFLOCK(f2,0);
+
+ if(f2->push != f2)
+ { /* freeze the pushed stream */
+ f2->mode |= SF_PUSH;
+ f1->push = f2;
+ rf = f1;
+ }
+ else
+ { /* unfreeze the just exposed stream */
+ f1->mode &= ~SF_PUSH;
+ f2->push = NIL(Sfio_t*);
+ rf = f2;
+ }
+
+ SFOPEN(f1,0);
+ SFOPEN(f2,0);
+
+ STKMTXRETURN(f1,f2, rf);
+}
diff --git a/src/lib/libast/sfio/sfstrtod.c b/src/lib/libast/sfio/sfstrtod.c
new file mode 100644
index 0000000..375d09f
--- /dev/null
+++ b/src/lib/libast/sfio/sfstrtod.c
@@ -0,0 +1,157 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Convert a Sfdouble_t value represented in an ASCII format into
+** the internal Sfdouble_t representation.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define BATCH (2*sizeof(int)) /* accumulate this many digits at a time */
+#define IPART 0 /* doing integer part */
+#define FPART 1 /* doing fractional part */
+#define EPART 2 /* doing exponent part */
+
+#if __STD_C
+static Sfdouble_t sfpow10(reg int n)
+#else
+static Sfdouble_t sfpow10(n)
+reg int n;
+#endif
+{
+ Sfdouble_t dval;
+
+ switch(n)
+ { case -3: return .001;
+ case -2: return .01;
+ case -1: return .1;
+ case 0: return 1.;
+ case 1: return 10.;
+ case 2: return 100.;
+ case 3: return 1000.;
+ }
+
+ if(n < 0)
+ { dval = .0001;
+ for(n += 4; n < 0; n += 1)
+ dval /= 10.;
+ }
+ else
+ { dval = 10000.;
+ for(n -= 4; n > 0; n -= 1)
+ dval *= 10.;
+ }
+
+ return dval;
+}
+
+#if __STD_C
+Sfdouble_t _sfstrtod(reg const char* s, char** retp)
+#else
+Sfdouble_t _sfstrtod(s,retp)
+reg char* s; /* string to convert */
+char** retp; /* to return the remainder of string */
+#endif
+{
+ reg int n, c, m;
+ reg int mode, fexp, sign, expsign;
+ Sfdouble_t dval;
+#if _lib_locale
+ int decpoint = 0;
+ int thousand = 0;
+ SFSETLOCALE(&decpoint,&thousand);
+#else
+#define decpoint '.'
+#endif
+
+ /* skip initial blanks */
+ while(isspace(*s))
+ ++s;
+
+ /* get the sign */
+ if((sign = (*s == '-')) || *s == '+')
+ s += 1;
+
+ mode = IPART;
+ fexp = expsign = 0;
+ dval = 0.;
+ while(*s)
+ { /* accumulate a handful of the digits */
+ for(m = BATCH, n = 0; m > 0; --m, ++s)
+ { /* get and process a char */
+ c = *s;
+ if(isdigit(c))
+ n = 10*n + (c - '0');
+ else break;
+ }
+
+ /* number of digits accumulated */
+ m = BATCH-m;
+
+ if(mode == IPART)
+ { /* doing the integer part */
+ if(dval == 0.)
+ dval = (Sfdouble_t)n;
+ else dval = dval*sfpow10(m) + (Sfdouble_t)n;
+ }
+ else if(mode == FPART)
+ { /* doing the fractional part */
+ fexp -= m;
+ if(n > 0)
+ dval += n*sfpow10(fexp);
+ }
+ else if(n)
+ { /* doing the exponent part */
+ if(expsign)
+ n = -n;
+ dval *= sfpow10(n);
+ }
+
+ if(!c)
+ break;
+
+ if(m < BATCH)
+ { /* detected a non-digit */
+ if(c == decpoint)
+ { /* start the fractional part or no match */
+ if(mode != IPART)
+ break;
+ mode = FPART;
+ s += 1;
+ }
+ else if(c == 'e' || c == 'E')
+ { if(mode == EPART)
+ break;
+ mode = EPART;
+ c = *++s;
+ if((expsign = (c == '-')) || c == '+')
+ s += 1;
+ }
+ else break;
+ }
+ }
+
+ if(retp)
+ *retp = (char*)s;
+ return sign ? -dval : dval;
+}
diff --git a/src/lib/libast/sfio/sfstrtof.h b/src/lib/libast/sfio/sfstrtof.h
new file mode 100644
index 0000000..37b28ec
--- /dev/null
+++ b/src/lib/libast/sfio/sfstrtof.h
@@ -0,0 +1,568 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * AT&T Research
+ * Glenn Fowler & Phong Vo
+ *
+ * common header and implementation for
+ *
+ * strtof strtod strtold _sfdscan
+ * strntof strntod strntold
+ *
+ * define these macros to instantiate an implementation:
+ *
+ * S2F_function the function name
+ * S2F_static <0:export =0:extern >0:static
+ * S2F_type 0:float 1:double 2:long.double
+ * S2F_qualifier 1 for optional [fFlL] qualifier suffix
+ * S2F_size 1 for interface with size_t second arg
+ * S2F_scan 1 for alternate interface with these arguments:
+ * void* handle
+ * int (*getchar)(void* handle, int flag)
+ * exactly one extra (*getchar)() is done, i.e.,
+ * the caller must do the pushback
+ * flag==0 get next char
+ * flag==1 no number seen
+ * return 0 on error or EOF
+ */
+
+#include "sfhdr.h"
+#include "FEATURE/float"
+
+/*
+ * the default is _sfdscan for standalone sfio compatibility
+ */
+
+#if !defined(S2F_function)
+#define S2F_function _sfdscan
+#define S2F_static 1
+#define S2F_type 2
+#define S2F_scan 1
+#ifndef elementsof
+#define elementsof(a) (sizeof(a)/sizeof(a[0]))
+#endif
+#endif
+
+#if S2F_type == 2 && _ast_fltmax_double
+#undef S2F_type
+#define S2F_type 1
+#endif
+
+#if S2F_type == 0
+#define S2F_number float
+#define S2F_ldexp ldexp
+#define S2F_pow10 _Sffpow10
+#define S2F_inf _Sffinf
+#define S2F_nan _Sffnan
+#define S2F_min (FLT_MIN)
+#define S2F_max (FLT_MAX)
+#define S2F_exp_10_min (FLT_MIN_10_EXP)
+#define S2F_exp_10_max (FLT_MAX_10_EXP)
+#define S2F_exp_2_min (FLT_MIN_EXP)
+#define S2F_exp_2_max (FLT_MAX_EXP)
+#endif
+#if S2F_type == 1
+#define S2F_number double
+#define S2F_ldexp ldexp
+#define S2F_pow10 _Sfdpow10
+#define S2F_inf _Sfdinf
+#define S2F_nan _Sfdnan
+#define S2F_min (DBL_MIN)
+#define S2F_max (DBL_MAX)
+#define S2F_exp_10_min (DBL_MIN_10_EXP)
+#define S2F_exp_10_max (DBL_MAX_10_EXP)
+#define S2F_exp_2_min (DBL_MIN_EXP)
+#define S2F_exp_2_max (DBL_MAX_EXP)
+#endif
+#if S2F_type == 2
+#define S2F_number long double
+#define S2F_ldexp ldexpl
+#define S2F_pow10 _Sflpow10
+#define S2F_inf _Sflinf
+#define S2F_nan _Sflnan
+#define S2F_min (LDBL_MIN)
+#define S2F_max (LDBL_MAX)
+#define S2F_exp_10_min (LDBL_MIN_10_EXP)
+#define S2F_exp_10_max (LDBL_MAX_10_EXP)
+#define S2F_exp_2_min (LDBL_MIN_EXP)
+#define S2F_exp_2_max (LDBL_MAX_EXP)
+#endif
+
+#if -S2F_exp_10_min < S2F_exp_10_max
+#define S2F_exp_10_abs (-S2F_exp_10_min)
+#else
+#define S2F_exp_10_abs S2F_exp_10_max
+#endif
+
+#define S2F_batch _ast_flt_unsigned_max_t
+
+#undef ERR /* who co-opted this namespace? */
+
+#if S2F_scan
+
+typedef int (*S2F_get_f)_ARG_((void*, int));
+
+#define ERR(e)
+#define GET(p) (*get)(p,0)
+#define NON(p) (*get)(p,1)
+#define PUT(p)
+#define REV(p,t,b)
+#define SET(p,t,b)
+
+#else
+
+#define ERR(e) (errno=(e))
+#define NON(p)
+
+#if S2F_size
+#define GET(p) (((p)<(z))?(*p++):(back=0))
+#define PUT(p) (end?(*end=(char*)p-back):(char*)0)
+#define REV(p,t,b) (p=t,back=b)
+#define SET(p,t,b) (t=p,b=back)
+#else
+#define GET(p) (*p++)
+#define PUT(p) (end?(*end=(char*)p-1):(char*)0)
+#define REV(p,t,b) (p=t)
+#define SET(p,t,b) (t=p)
+#endif
+
+#endif
+
+typedef struct S2F_part_s
+{
+ S2F_batch batch;
+ int digits;
+} S2F_part_t;
+
+#if !defined(ERANGE)
+#define ERANGE EINVAL
+#endif
+
+#if S2F_static > 0
+static
+#else
+#if S2F_static < 0 || !defined(S2F_static)
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+extern
+#undef extern
+#endif
+#endif
+S2F_number
+#if S2F_scan
+#if __STD_C
+S2F_function(void* s, S2F_get_f get)
+#else
+S2F_function(s, get) void* s; S2F_get_f get;
+#endif
+#else
+#if S2F_size
+#if __STD_C
+S2F_function(const char* str, size_t size, char** end)
+#else
+S2F_function(str, size, end) char* str; size_t size; char** end;
+#endif
+#else
+#if __STD_C
+S2F_function(const char* str, char** end)
+#else
+S2F_function(str, end) char* str; char** end;
+#endif
+#endif
+#endif
+{
+#if !S2F_scan
+ register unsigned char* s = (unsigned char*)str;
+#if S2F_size
+ register unsigned char* z = s + size;
+ int back = 1;
+ int b;
+#endif
+ unsigned char* t;
+#endif
+ register S2F_batch n;
+ register int c;
+ register int digits;
+ register int m;
+ register unsigned char* cv;
+ int negative;
+ int enegative;
+ int fraction;
+ int decimal = 0;
+ int thousand = 0;
+ int part = 0;
+ int back_part;
+ S2F_batch back_n;
+ S2F_number v;
+ S2F_number p;
+ S2F_part_t parts[16];
+
+ /*
+ * radix char and thousands separator are locale specific
+ */
+
+ SFSETLOCALE(&decimal, &thousand);
+ SFCVINIT();
+
+ /*
+ * skip initial blanks
+ */
+
+ do c = GET(s); while (isspace(c));
+ SET(s, t, b);
+
+ /*
+ * get the sign
+ */
+
+ if ((negative = (c == '-')) || c == '+')
+ c = GET(s);
+
+ /*
+ * drop leading 0's
+ */
+
+ digits = 0;
+ fraction = -1;
+ if (c == '0')
+ {
+ c = GET(s);
+ if (c == 'x' || c == 'X')
+ {
+ /*
+ * hex floating point -- easy
+ */
+
+ cv = _Sfcv36;
+ v = 0;
+ for (;;)
+ {
+ c = GET(s);
+ if ((part = cv[c]) < 16)
+ {
+ digits++;
+ v *= 16;
+ v += part;
+ }
+ else if (c == decimal)
+ {
+ decimal = -1;
+ fraction = digits;
+ }
+ else
+ break;
+ }
+ m = 0;
+ if (c == 'p' || c == 'P')
+ {
+ c = GET(s);
+ if ((enegative = c == '-') || c == '+')
+ c = GET(s);
+ while (c >= '0' && c <= '9')
+ {
+ m = (m << 3) + (m << 1) + (c - '0');
+ c = GET(s);
+ }
+ if (enegative)
+ m = -m;
+ }
+
+#if S2F_qualifier
+
+ /*
+ * consume the optional suffix
+ */
+
+ switch (c)
+ {
+ case 'f':
+ case 'F':
+ case 'l':
+ case 'L':
+ c = GET(s);
+ break;
+ }
+#endif
+ PUT(s);
+ if (v == 0)
+ return negative ? -v : v;
+ if (fraction >= 0)
+ m -= 4 * (digits - fraction);
+ if (m < S2F_exp_2_min)
+ {
+ if ((m -= S2F_exp_2_min) < S2F_exp_2_min)
+ {
+ ERR(ERANGE);
+ return 0;
+ }
+ v = S2F_ldexp(v, S2F_exp_2_min);
+ }
+ else if (m > S2F_exp_2_max)
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+ v = S2F_ldexp(v, m);
+ goto check;
+ }
+ while (c == '0')
+ c = GET(s);
+ }
+ else if (c == decimal)
+ {
+ decimal = -1;
+ fraction = 0;
+ for (;;)
+ {
+ c = GET(s);
+ if (c != '0')
+ break;
+ digits++;
+ }
+ }
+ else if (c == 'i' || c == 'I')
+ {
+ if ((c = GET(s)) != 'n' && c != 'N' ||
+ (c = GET(s)) != 'f' && c != 'F')
+ {
+ REV(s, t, b);
+ PUT(s);
+ return 0;
+ }
+ c = GET(s);
+ SET(s, t, b);
+ if (((c) == 'i' || c == 'I') &&
+ ((c = GET(s)) == 'n' || c == 'N') &&
+ ((c = GET(s)) == 'i' || c == 'I') &&
+ ((c = GET(s)) == 't' || c == 'T') &&
+ ((c = GET(s)) == 'y' || c == 'Y'))
+ {
+ c = GET(s);
+ SET(s, t, b);
+ }
+ REV(s, t, b);
+ PUT(s);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+ else if (c == 'n' || c == 'N')
+ {
+ if ((c = GET(s)) != 'a' && c != 'A' ||
+ (c = GET(s)) != 'n' && c != 'N')
+ {
+ REV(s, t, b);
+ PUT(s);
+ return 0;
+ }
+ do c = GET(s); while (c && !isspace(c));
+ PUT(s);
+ return negative ? -S2F_nan : S2F_nan;
+ }
+ else if (c < '1' || c > '9')
+ {
+ REV(s, t, b);
+ PUT(s);
+ NON(s);
+ return 0;
+ }
+
+ /*
+ * consume the integral and fractional parts
+ */
+
+ n = 0;
+ m = 0;
+ for (;;)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ digits++;
+ n = (n << 3) + (n << 1) + (c - '0');
+ if (n >= ((~((S2F_batch)0)) / 10) && part < elementsof(parts))
+ {
+ parts[part].batch = n;
+ n = 0;
+ parts[part].digits = digits;
+ part++;
+ }
+ }
+ else if (m && (digits - m) != 3)
+ break;
+ else if (c == decimal)
+ {
+ decimal = -1;
+ thousand = -1;
+ m = 0;
+ fraction = digits;
+ }
+ else if (c != thousand)
+ break;
+ else if (!(m = digits))
+ {
+ SET(s, t, b);
+ break;
+ }
+ else
+ {
+ SET(s, t, b);
+ back_n = n;
+ back_part = part;
+ }
+ c = GET(s);
+ }
+ if (m && (digits - m) != 3)
+ {
+ REV(s, t, b);
+ n = back_n;
+ part = back_part;
+ }
+
+ /*
+ * don't forget the last part
+ */
+
+ if (n && part < elementsof(parts))
+ {
+ parts[part].batch = n;
+ parts[part].digits = digits;
+ part++;
+ }
+
+ /*
+ * consume the exponent
+ */
+
+ if (fraction >= 0)
+ digits = fraction;
+ if (c == 'e' || c == 'E')
+ {
+ c = GET(s);
+ if ((enegative = (c == '-')) || c == '+')
+ c = GET(s);
+ n = 0;
+ while (c >= '0' && c <= '9')
+ {
+ n = (n << 3) + (n << 1) + (c - '0');
+ c = GET(s);
+ }
+ if (enegative)
+ digits -= n;
+ else
+ digits += n;
+ }
+
+#if S2F_qualifier
+
+ /*
+ * consume the optional suffix
+ */
+
+ switch (c)
+ {
+ case 'f':
+ case 'F':
+ case 'l':
+ case 'L':
+ c = GET(s);
+ break;
+ }
+#endif
+ PUT(s);
+
+ /*
+ * adjust for at most one multiply per part
+ * and at most one divide overall
+ */
+
+ v = 0;
+ if (!part)
+ return negative ? -v : v;
+ else if ((m = parts[part-1].digits - digits) > 0)
+ digits += m;
+ else
+ m = 0;
+
+ /*
+ * combine the parts
+ */
+
+ while (part--)
+ {
+ p = parts[part].batch;
+ c = digits - parts[part].digits;
+ if (c > S2F_exp_10_max)
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+ if (c > 0)
+ {
+#if _ast_mpy_overflow_fpe
+ if ((S2F_max / p) < S2F_pow10[c])
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+#endif
+ p *= S2F_pow10[c];
+ }
+ v += p;
+ }
+ if (m)
+ {
+ while (m > S2F_exp_10_max)
+ {
+ m -= S2F_exp_10_max;
+ v /= S2F_pow10[S2F_exp_10_max];
+ }
+#if _ast_div_underflow_fpe
+ if ((S2F_min * p) > S2F_pow10[c])
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+#endif
+ v /= S2F_pow10[m];
+ }
+
+ /*
+ * check the range
+ */
+
+ check:
+ if (v < S2F_min)
+ {
+ ERR(ERANGE);
+ v = 0;
+ }
+ else if (v > S2F_max)
+ {
+ ERR(ERANGE);
+ v = S2F_inf;
+ }
+
+ /*
+ * done
+ */
+
+ return negative ? -v : v;
+}
diff --git a/src/lib/libast/sfio/sfswap.c b/src/lib/libast/sfio/sfswap.c
new file mode 100644
index 0000000..4ffc614
--- /dev/null
+++ b/src/lib/libast/sfio/sfswap.c
@@ -0,0 +1,119 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Swap two streams. If the second argument is NULL,
+** a new stream will be created. Always return the second argument
+** or the new stream. Note that this function will always work
+** unless streams are locked by SF_PUSH.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Sfio_t* sfswap(reg Sfio_t* f1, reg Sfio_t* f2)
+#else
+Sfio_t* sfswap(f1,f2)
+reg Sfio_t* f1;
+reg Sfio_t* f2;
+#endif
+{
+ Sfio_t tmp;
+ int f1pool, f2pool, f1mode, f2mode, f1flags, f2flags;
+
+ if(!f1 || (f1->mode&SF_AVAIL) || (SFFROZEN(f1) && (f1->mode&SF_PUSH)) )
+ return NIL(Sfio_t*);
+ if(f2 && SFFROZEN(f2) && (f2->mode&SF_PUSH) )
+ return NIL(Sfio_t*);
+ if(f1 == f2)
+ return f2;
+
+ f1mode = f1->mode;
+ SFLOCK(f1,0);
+ f1->mode |= SF_PUSH; /* make sure there is no recursion on f1 */
+
+ if(f2)
+ { f2mode = f2->mode;
+ SFLOCK(f2,0);
+ f2->mode |= SF_PUSH; /* make sure there is no recursion on f2 */
+ }
+ else
+ { f2 = f1->file == 0 ? sfstdin :
+ f1->file == 1 ? sfstdout :
+ f1->file == 2 ? sfstderr : NIL(Sfio_t*);
+ if((!f2 || !(f2->mode&SF_AVAIL)) )
+ { if(!(f2 = (Sfio_t*)malloc(sizeof(Sfio_t))) )
+ { f1->mode = f1mode;
+ SFOPEN(f1,0);
+ return NIL(Sfio_t*);
+ }
+
+ SFCLEAR(f2,NIL(Vtmutex_t*));
+ }
+ f2->mode = SF_AVAIL|SF_LOCK;
+ f2mode = SF_AVAIL;
+ }
+
+ if(!f1->pool)
+ f1pool = -1;
+ else for(f1pool = f1->pool->n_sf-1; f1pool >= 0; --f1pool)
+ if(f1->pool->sf[f1pool] == f1)
+ break;
+ if(!f2->pool)
+ f2pool = -1;
+ else for(f2pool = f2->pool->n_sf-1; f2pool >= 0; --f2pool)
+ if(f2->pool->sf[f2pool] == f2)
+ break;
+
+ f1flags = f1->flags;
+ f2flags = f2->flags;
+
+ /* swap image and pool entries */
+ memcpy((Void_t*)(&tmp),(Void_t*)f1,sizeof(Sfio_t));
+ memcpy((Void_t*)f1,(Void_t*)f2,sizeof(Sfio_t));
+ memcpy((Void_t*)f2,(Void_t*)(&tmp),sizeof(Sfio_t));
+ if(f2pool >= 0)
+ f1->pool->sf[f2pool] = f1;
+ if(f1pool >= 0)
+ f2->pool->sf[f1pool] = f2;
+
+ if(f2flags&SF_STATIC)
+ f2->flags |= SF_STATIC;
+ else f2->flags &= ~SF_STATIC;
+
+ if(f1flags&SF_STATIC)
+ f1->flags |= SF_STATIC;
+ else f1->flags &= ~SF_STATIC;
+
+ if(f2mode&SF_AVAIL) /* swapping to a closed stream */
+ { if(!(f1->flags&SF_STATIC) )
+ free(f1);
+ }
+ else
+ { f1->mode = f2mode;
+ SFOPEN(f1,0);
+ }
+
+ f2->mode = f1mode;
+ SFOPEN(f2,0);
+ return f2;
+}
diff --git a/src/lib/libast/sfio/sfsync.c b/src/lib/libast/sfio/sfsync.c
new file mode 100644
index 0000000..4a9d16f
--- /dev/null
+++ b/src/lib/libast/sfio/sfsync.c
@@ -0,0 +1,172 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Synchronize data in buffers with the file system.
+** If f is nil, all streams are sync-ed
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static int _sfall(void)
+#else
+static int _sfall()
+#endif
+{
+ reg Sfpool_t *p, *next;
+ reg Sfio_t* f;
+ reg int n, rv;
+ reg int nsync, count, loop;
+#define MAXLOOP 3
+
+ for(loop = 0; loop < MAXLOOP; ++loop)
+ { rv = nsync = count = 0;
+ for(p = &_Sfpool; p; p = next)
+ { /* find the next legitimate pool */
+ for(next = p->next; next; next = next->next)
+ if(next->n_sf > 0)
+ break;
+
+ /* walk the streams for _Sfpool only */
+ for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n)
+ { count += 1;
+ f = p->sf[n];
+
+ if(f->flags&SF_STRING )
+ goto did_sync;
+ if(SFFROZEN(f))
+ continue;
+ if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
+ goto did_sync;
+ if((f->mode&SF_READ) && !(f->bits&SF_MMAP) &&
+ f->next == f->endb)
+ goto did_sync;
+ if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) &&
+ f->next == f->data)
+ goto did_sync;
+
+ if(sfsync(f) < 0)
+ rv = -1;
+
+ did_sync:
+ nsync += 1;
+ }
+ }
+
+ if(nsync == count)
+ break;
+ }
+ return rv;
+}
+
+#if __STD_C
+int sfsync(reg Sfio_t* f)
+#else
+int sfsync(f)
+reg Sfio_t* f; /* stream to be synchronized */
+#endif
+{
+ int local, rv, mode, lock;
+ Sfio_t* origf;
+ SFMTXDECL(f);
+
+ if(!(origf = f) )
+ return _sfall();
+
+ SFMTXENTER(origf,-1);
+
+ GETLOCAL(origf,local);
+
+ if(origf->disc == _Sfudisc) /* throw away ungetc */
+ (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*)));
+
+ rv = 0;
+
+ lock = origf->mode&SF_LOCK;
+ if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */
+ goto done;
+
+ if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0)
+ { rv = -1;
+ goto done;
+ }
+
+ for(; f; f = f->push)
+ {
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc);
+
+ SFLOCK(f,local);
+
+ /* pretend that this stream is not on a stack */
+ mode = f->mode&SF_PUSH;
+ f->mode &= ~SF_PUSH;
+
+ /* these streams do not need synchronization */
+ if((f->flags&SF_STRING) || (f->mode&SF_SYNCED))
+ goto next;
+
+ if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) )
+ { /* sync the buffer, make sure pool don't move */
+ reg int pool = f->mode&SF_POOL;
+ f->mode &= ~SF_POOL;
+ if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0)
+ rv = -1;
+ if(!SFISNULL(f) && (f->bits&SF_HOLE) )
+ { /* realize a previously created hole of 0's */
+ if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0)
+ (void)SFWR(f,"",1,f->disc);
+ f->bits &= ~SF_HOLE;
+ }
+ f->mode |= pool;
+ }
+
+ if((f->mode&SF_READ) && f->extent >= 0 &&
+ ((f->bits&SF_MMAP) || f->next < f->endb) )
+ { /* make sure the file pointer is at the right place */
+ f->here -= (f->endb-f->next);
+ f->endr = f->endw = f->data;
+ f->mode = SF_READ|SF_SYNCED|lock;
+ (void)SFSK(f,f->here,SEEK_SET,f->disc);
+
+ if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) &&
+ !(f->bits&SF_MMAP) )
+ { f->endb = f->next = f->data;
+ f->mode &= ~SF_SYNCED;
+ }
+ }
+
+ next:
+ f->mode |= mode;
+ SFOPEN(f,local);
+
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc);
+ }
+
+done:
+ if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0])
+ SFSYNC(f->pool->sf[0]);
+
+ SFMTXRETURN(origf, rv);
+}
diff --git a/src/lib/libast/sfio/sftable.c b/src/lib/libast/sfio/sftable.c
new file mode 100644
index 0000000..c165bae
--- /dev/null
+++ b/src/lib/libast/sfio/sftable.c
@@ -0,0 +1,543 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+#include "FEATURE/float"
+
+/* Dealing with $ argument addressing stuffs.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static char* sffmtint(const char* str, int* v)
+#else
+static char* sffmtint(str, v)
+char* str;
+int* v;
+#endif
+{
+ for(*v = 0; isdigit(*str); ++str)
+ *v = *v * 10 + (*str - '0');
+ *v -= 1;
+ return (char*)str;
+}
+
+#if __STD_C
+static Fmtpos_t* sffmtpos(Sfio_t* f,const char* form,va_list args,Sffmt_t* ft,int type)
+#else
+static Fmtpos_t* sffmtpos(f,form,args,ft,type)
+Sfio_t* f;
+char* form;
+va_list args;
+Sffmt_t* ft;
+int type; /* >0: scanf, =0: printf, -1: internal */
+#endif
+{
+ int base, fmt, flags, dot, width, precis;
+ ssize_t n_str, size;
+ char *t_str, *sp;
+ int v, n, skip, dollar, decimal, thousand;
+ Sffmt_t savft;
+ Fmtpos_t* fp; /* position array of arguments */
+ int argp, argn, maxp, need[FP_INDEX];
+#if _has_multibyte
+ SFMBDCL(fmbs)
+#endif
+
+ if(type < 0)
+ fp = NIL(Fmtpos_t*);
+ else if(!(fp = sffmtpos(f,form,args,ft,-1)) )
+ return NIL(Fmtpos_t*);
+
+ dollar = decimal = thousand = 0; argn = maxp = -1;
+ SFMBCLR(&fmbs);
+ while((n = *form) )
+ { if(n != '%') /* collect the non-pattern chars */
+ { sp = (char*)form;
+ for(;;)
+ { form += SFMBLEN(form, &fmbs);
+ if(*form == 0 || *form == '%')
+ break;
+ }
+ continue;
+ }
+ else form += 1;
+ if(*form == 0)
+ break;
+ else if(*form == '%')
+ { form += 1;
+ continue;
+ }
+
+ if(*form == '*' && type > 0) /* skip in scanning */
+ { skip = 1;
+ form += 1;
+ argp = -1;
+ }
+ else /* get the position of this argument */
+ { skip = 0;
+ sp = sffmtint(form,&argp);
+ if(*sp == '$')
+ { dollar = 1;
+ form = sp+1;
+ }
+ else argp = -1;
+ }
+
+ flags = dot = 0;
+ t_str = NIL(char*); n_str = 0;
+ size = width = precis = base = -1;
+ for(n = 0; n < FP_INDEX; ++n)
+ need[n] = -1;
+
+ loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
+ switch((fmt = *form++) )
+ {
+ case LEFTP : /* get the type enclosed in balanced parens */
+ t_str = (char*)form;
+ for(v = 1;;)
+ { switch(*form++)
+ {
+ case 0 : /* not balancable, retract */
+ form = t_str;
+ t_str = NIL(char*);
+ n_str = 0;
+ goto loop_flags;
+ case LEFTP : /* increasing nested level */
+ v += 1;
+ continue;
+ case RIGHTP : /* decreasing nested level */
+ if((v -= 1) != 0)
+ continue;
+ n_str = form-t_str;
+ if(*t_str == '*')
+ { t_str = sffmtint(t_str+1,&n);
+ if(*t_str == '$')
+ dollar = 1;
+ else n = -1;
+ if((n = FP_SET(n,argn)) > maxp)
+ maxp = n;
+ if(fp && fp[n].ft.fmt == 0)
+ { fp[n].ft.fmt = LEFTP;
+ fp[n].ft.form = (char*)form;
+ }
+ need[FP_STR] = n;
+ }
+ goto loop_flags;
+ }
+ }
+
+ case '-' :
+ flags |= SFFMT_LEFT;
+ flags &= ~SFFMT_ZERO;
+ goto loop_flags;
+ case '0' :
+ if(!(flags&SFFMT_LEFT) )
+ flags |= SFFMT_ZERO;
+ goto loop_flags;
+ case ' ' :
+ if(!(flags&SFFMT_SIGN) )
+ flags |= SFFMT_BLANK;
+ goto loop_flags;
+ case '+' :
+ flags |= SFFMT_SIGN;
+ flags &= ~SFFMT_BLANK;
+ goto loop_flags;
+ case '#' :
+ flags |= SFFMT_ALTER;
+ goto loop_flags;
+ case QUOTE:
+ SFSETLOCALE(&decimal,&thousand);
+ if(thousand > 0)
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+
+ case '.' :
+ if((dot += 1) == 2)
+ base = 0; /* for %s,%c */
+ if(isdigit(*form))
+ { fmt = *form++;
+ goto dot_size;
+ }
+ else if(*form != '*')
+ goto loop_flags;
+ else form += 1; /* drop thru below */
+
+ case '*' :
+ form = sffmtint(form,&n);
+ if(*form == '$' )
+ { dollar = 1;
+ form += 1;
+ }
+ else n = -1;
+ if((n = FP_SET(n,argn)) > maxp)
+ maxp = n;
+ if(fp && fp[n].ft.fmt == 0)
+ { fp[n].ft.fmt = '.';
+ fp[n].ft.size = dot;
+ fp[n].ft.form = (char*)form;
+ }
+ if(dot <= 2)
+ need[dot] = n;
+ goto loop_flags;
+
+ case '1' : case '2' : case '3' :
+ case '4' : case '5' : case '6' :
+ case '7' : case '8' : case '9' :
+ dot_size :
+ for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form)
+ v = v*10 + (fmt - '0');
+ if(dot == 0)
+ width = v;
+ else if(dot == 1)
+ precis = v;
+ else if(dot == 2)
+ base = v;
+ goto loop_flags;
+
+ case 'I' : /* object length */
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
+ if(isdigit(*form) )
+ { for(size = 0, n = *form; isdigit(n); n = *++form)
+ size = size*10 + (n - '0');
+ }
+ else if(*form == '*')
+ { form = sffmtint(form+1,&n);
+ if(*form == '$' )
+ { dollar = 1;
+ form += 1;
+ }
+ else n = -1;
+ if((n = FP_SET(n,argn)) > maxp)
+ maxp = n;
+ if(fp && fp[n].ft.fmt == 0)
+ { fp[n].ft.fmt = 'I';
+ fp[n].ft.size = sizeof(int);
+ fp[n].ft.form = (char*)form;
+ }
+ need[FP_SIZE] = n;
+ }
+ goto loop_flags;
+
+ case 'l' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'l')
+ { form += 1;
+ flags |= SFFMT_LLONG;
+ }
+ else flags |= SFFMT_LONG;
+ goto loop_flags;
+ case 'h' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'h')
+ { form += 1;
+ flags |= SFFMT_SSHORT;
+ }
+ else flags |= SFFMT_SHORT;
+ goto loop_flags;
+ case 'L' :
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
+ goto loop_flags;
+ }
+
+ /* set object size for scalars */
+ if(flags & SFFMT_TYPES)
+ { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
+ { if(flags&SFFMT_LONG)
+ size = sizeof(long);
+ else if(flags&SFFMT_SHORT)
+ size = sizeof(short);
+ else if(flags&SFFMT_SSHORT)
+ size = sizeof(char);
+ else if(flags&SFFMT_TFLAG)
+ size = sizeof(ptrdiff_t);
+ else if(flags&SFFMT_ZFLAG)
+ size = sizeof(size_t);
+ else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
+ size = sizeof(Sflong_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0 ||
+ size == sizeof(Sflong_t)*CHAR_BIT )
+ size = sizeof(Sflong_t);
+ }
+ else if(size < 0)
+ size = sizeof(int);
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT)
+ { if(flags&(SFFMT_LONG|SFFMT_LLONG))
+ size = sizeof(double);
+ else if(flags&SFFMT_LDOUBLE)
+ size = sizeof(Sfdouble_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0)
+ size = sizeof(Sfdouble_t);
+ }
+ else if(size < 0)
+ size = sizeof(float);
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ {
+#if _has_multibyte
+ if((flags&SFFMT_LONG) || fmt == 'C')
+ { size = sizeof(wchar_t) > sizeof(int) ?
+ sizeof(wchar_t) : sizeof(int);
+ } else
+#endif
+ if(size < 0)
+ size = sizeof(int);
+ }
+ }
+
+ if(skip)
+ continue;
+
+ if((argp = FP_SET(argp,argn)) > maxp)
+ maxp = argp;
+
+ if(dollar && fmt == '!')
+ return NIL(Fmtpos_t*);
+
+ if(fp && fp[argp].ft.fmt == 0)
+ { fp[argp].ft.form = (char*)form;
+ fp[argp].ft.fmt = fp[argp].fmt = fmt;
+ fp[argp].ft.size = size;
+ fp[argp].ft.flags = flags;
+ fp[argp].ft.width = width;
+ fp[argp].ft.precis = precis;
+ fp[argp].ft.base = base;
+ fp[argp].ft.t_str = t_str;
+ fp[argp].ft.n_str = n_str;
+ for(n = 0; n < FP_INDEX; ++n)
+ fp[argp].need[n] = need[n];
+ }
+ }
+
+ if(!fp) /* constructing position array only */
+ { if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) )
+ return NIL(Fmtpos_t*);
+ for(n = 0; n <= maxp; ++n)
+ fp[n].ft.fmt = 0;
+ return fp;
+ }
+
+ /* get value for positions */
+ if(ft)
+ memcpy(&savft, ft, sizeof(*ft));
+ for(n = 0; n <= maxp; ++n)
+ { if(fp[n].ft.fmt == 0) /* gap: pretend it's a 'd' pattern */
+ { fp[n].ft.fmt = 'd';
+ fp[n].ft.width = 0;
+ fp[n].ft.precis = 0;
+ fp[n].ft.base = 0;
+ fp[n].ft.size = 0;
+ fp[n].ft.t_str = 0;
+ fp[n].ft.n_str = 0;
+ fp[n].ft.flags = 0;
+ for(v = 0; v < FP_INDEX; ++v)
+ fp[n].need[v] = -1;
+ }
+
+ if(ft && ft->extf)
+ { fp[n].ft.version = ft->version;
+ fp[n].ft.extf = ft->extf;
+ fp[n].ft.eventf = ft->eventf;
+ if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n)
+ fp[n].ft.width = fp[v].argv.i;
+ if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n)
+ fp[n].ft.precis = fp[v].argv.i;
+ if((v = fp[n].need[FP_BASE]) >= 0 && v < n)
+ fp[n].ft.base = fp[v].argv.i;
+ if((v = fp[n].need[FP_STR]) >= 0 && v < n)
+ fp[n].ft.t_str = fp[v].argv.s;
+ if((v = fp[n].need[FP_SIZE]) >= 0 && v < n)
+ fp[n].ft.size = fp[v].argv.i;
+
+ memcpy(ft,&fp[n].ft,sizeof(Sffmt_t));
+ va_copy(ft->args,args);
+ ft->flags |= SFFMT_ARGPOS;
+ v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft);
+ va_copy(args,ft->args);
+ memcpy(&fp[n].ft,ft,sizeof(Sffmt_t));
+ if(v < 0)
+ { memcpy(ft,&savft,sizeof(Sffmt_t));
+ ft = NIL(Sffmt_t*);
+ }
+
+ if(!(fp[n].ft.flags&SFFMT_VALUE) )
+ goto arg_list;
+ else if(_Sftype[fp[n].ft.fmt]&(SFFMT_INT|SFFMT_UINT) )
+ { if(fp[n].ft.size == sizeof(short))
+ { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
+ fp[n].argv.i = fp[n].argv.h;
+ else fp[n].argv.i = fp[n].argv.uh;
+ }
+ else if(fp[n].ft.size == sizeof(char))
+ { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
+ fp[n].argv.i = fp[n].argv.c;
+ else fp[n].argv.i = fp[n].argv.uc;
+ }
+ }
+ else if(_Sftype[fp[n].ft.fmt]&SFFMT_FLOAT )
+ { if(fp[n].ft.size == sizeof(float) )
+ fp[n].argv.d = fp[n].argv.f;
+ }
+ }
+ else
+ { arg_list:
+ if(fp[n].ft.fmt == LEFTP)
+ { fp[n].argv.s = va_arg(args, char*);
+ fp[n].ft.size = strlen(fp[n].argv.s);
+ }
+ else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I')
+ fp[n].argv.i = va_arg(args, int);
+ else if(fp[n].ft.fmt == '!')
+ { if(ft)
+ memcpy(ft,&savft,sizeof(Sffmt_t));
+ fp[n].argv.ft = ft = va_arg(args, Sffmt_t*);
+ if(ft->form)
+ ft = NIL(Sffmt_t*);
+ if(ft)
+ memcpy(&savft,ft,sizeof(Sffmt_t));
+ }
+ else if(type > 0) /* from sfvscanf */
+ fp[n].argv.vp = va_arg(args, Void_t*);
+ else switch(_Sftype[fp[n].ft.fmt])
+ { case SFFMT_INT:
+ case SFFMT_UINT:
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t) )
+ fp[n].argv.ll = va_arg(args, Sflong_t);
+ else
+#endif
+ if(size == sizeof(long) )
+ fp[n].argv.l = va_arg(args, long);
+ else fp[n].argv.i = va_arg(args, int);
+ break;
+ case SFFMT_FLOAT:
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t) )
+ fp[n].argv.ld = va_arg(args,Sfdouble_t);
+ else
+#endif
+ fp[n].argv.d = va_arg(args,double);
+ break;
+ case SFFMT_POINTER:
+ fp[n].argv.vp = va_arg(args,Void_t*);
+ break;
+ case SFFMT_CHAR:
+ if(fp[n].ft.base >= 0)
+ fp[n].argv.s = va_arg(args,char*);
+#if _has_multibyte
+ else if((fp[n].ft.flags & SFFMT_LONG) ||
+ fp[n].ft.fmt == 'C' )
+ { if(sizeof(wchar_t) <= sizeof(int) )
+ fp[n].argv.wc = (wchar_t)va_arg(args,int);
+ else fp[n].argv.wc = va_arg(args,wchar_t);
+ }
+#endif
+ /* observe promotion rule */
+ else fp[n].argv.i = va_arg(args,int);
+ break;
+ default: /* unknown pattern */
+ break;
+ }
+ }
+ }
+
+ if(ft)
+ memcpy(ft,&savft,sizeof(Sffmt_t));
+ return fp;
+}
+
+static const unsigned char flt_nan[] = { _ast_flt_nan_init };
+static const unsigned char flt_inf[] = { _ast_flt_inf_init };
+static const unsigned char dbl_nan[] = { _ast_dbl_nan_init };
+static const unsigned char dbl_inf[] = { _ast_dbl_inf_init };
+#ifdef _ast_ldbl_nan_init
+static const unsigned char ldbl_nan[] = { _ast_ldbl_nan_init };
+static const unsigned char ldbl_inf[] = { _ast_ldbl_inf_init };
+#endif
+
+/* function to initialize conversion tables */
+static int sfcvinit()
+{ reg int d, l;
+
+ for(d = 0; d <= SF_MAXCHAR; ++d)
+ { _Sfcv36[d] = SF_RADIX;
+ _Sfcv64[d] = SF_RADIX;
+ }
+
+ /* [0-9] */
+ for(d = 0; d < 10; ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = d;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ /* [a-z] */
+ for(; d < 36; ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = d;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ /* [A-Z] */
+ for(l = 10; d < 62; ++l, ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = l;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ /* remaining digits */
+ for(; d < SF_RADIX; ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = d;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ _Sftype['d'] = _Sftype['i'] = SFFMT_INT;
+ _Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT;
+ _Sftype['e'] = _Sftype['E'] = _Sftype['a'] = _Sftype['A'] =
+ _Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT;
+ _Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER;
+ _Sftype['c'] = SFFMT_CHAR;
+ _Sftype['['] = SFFMT_CLASS;
+#if _has_multibyte
+ _Sftype['S'] = SFFMT_POINTER;
+ _Sftype['C'] = SFFMT_CHAR;
+#endif
+
+ /* IEEE floating point computed constants */
+
+ memcpy((char*)&_Sffnan, (char*)flt_nan, sizeof(_Sffnan));
+ memcpy((char*)&_Sffinf, (char*)flt_inf, sizeof(_Sffinf));
+ memcpy((char*)&_Sfdnan, (char*)dbl_nan, sizeof(_Sfdnan));
+ memcpy((char*)&_Sfdinf, (char*)dbl_inf, sizeof(_Sfdinf));
+#ifdef _ast_ldbl_nan_init
+ memcpy((char*)&_Sflnan, (char*)ldbl_nan, sizeof(_Sflnan));
+ memcpy((char*)&_Sflinf, (char*)ldbl_inf, sizeof(_Sflinf));
+#else
+ memcpy((char*)&_Sflnan, (char*)dbl_nan, sizeof(_Sfdnan));
+ memcpy((char*)&_Sflinf, (char*)dbl_inf, sizeof(_Sfdinf));
+#endif
+
+ return 1;
+}
+
+/* table for floating point and integer conversions */
+#include "FEATURE/sfinit"
diff --git a/src/lib/libast/sfio/sftell.c b/src/lib/libast/sfio/sftell.c
new file mode 100644
index 0000000..49c183c
--- /dev/null
+++ b/src/lib/libast/sfio/sftell.c
@@ -0,0 +1,59 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Tell the current location in a given stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Sfoff_t sftell(Sfio_t* f)
+#else
+Sfoff_t sftell(f)
+Sfio_t *f;
+#endif
+{
+ reg int mode;
+ Sfoff_t p;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ /* set the stream to the right mode */
+ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+
+ /* throw away ungetc data */
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ if(f->flags&SF_STRING)
+ SFMTXRETURN(f, (Sfoff_t)(f->next-f->data));
+
+ /* let sfseek() handle the hard case */
+ if(f->extent >= 0 && (f->flags&(SF_SHARE|SF_APPENDWR)) )
+ p = sfseek(f,(Sfoff_t)0,SEEK_CUR);
+ else p = f->here + ((f->mode&SF_WRITE) ? f->next-f->data : f->next-f->endb);
+
+ SFMTXRETURN(f,p);
+}
diff --git a/src/lib/libast/sfio/sftmp.c b/src/lib/libast/sfio/sftmp.c
new file mode 100644
index 0000000..4f804d6
--- /dev/null
+++ b/src/lib/libast/sfio/sftmp.c
@@ -0,0 +1,402 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Create a temporary stream for read/write.
+** The stream is originally created as a memory-resident stream.
+** When this memory is exceeded, a real temp file will be created.
+** The temp file creation sequence is somewhat convoluted so that
+** pool/stack/discipline will work correctly.
+**
+** Written by David Korn and Kiem-Phong Vo.
+*/
+
+#if _tmp_rmfail
+
+/* File not removable while there is an open file descriptor.
+** To ensure that temp files are properly removed, we need:
+** 1. A discipline to remove a file when the corresponding stream is closed.
+** Care must be taken to close the file descriptor before removing the
+** file because systems such as NT do not allow file removal while
+** there is an open file handle.
+** 2. An atexit() function is set up to close temp files when process exits.
+** 3. On systems with O_TEMPORARY (e.g., NT), this is used to further ensure
+** that temp files will be removed after the last handle is closed.
+*/
+
+typedef struct _file_s File_t;
+struct _file_s
+{ File_t* next; /* link list */
+ Sfio_t* f; /* associated stream */
+ char name[1]; /* temp file name */
+};
+
+static File_t* File; /* list pf temp files */
+
+#if __STD_C
+static int _tmprmfile(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _tmprmfile(f, type, val, disc)
+Sfio_t* f;
+int type;
+Void_t* val;
+Sfdisc_t* disc;
+#endif
+{
+ reg File_t *ff, *last;
+
+ NOTUSED(val);
+
+ if(type == SF_DPOP) /* don't allow this to pop */
+ return -1;
+
+ if(type == SF_CLOSING)
+ {
+ (void)vtmtxlock(_Sfmutex);
+ for(last = NIL(File_t*), ff = File; ff; last = ff, ff = ff->next)
+ if(ff->f == f)
+ break;
+ if(ff)
+ { if(!last)
+ File = ff->next;
+ else last->next = ff->next;
+
+ if(_Sfnotify)
+ (*_Sfnotify)(f,SF_CLOSING,f->file);
+ CLOSE(f->file);
+ f->file = -1;
+ while(sysremovef(ff->name) < 0 && errno == EINTR)
+ errno = 0;
+
+ free((Void_t*)ff);
+ }
+ (void)vtmtxunlock(_Sfmutex);
+ }
+
+ return 0;
+}
+
+#if __STD_C
+static void _rmfiles(void)
+#else
+static void _rmfiles()
+#endif
+{ reg File_t *ff, *next;
+
+ (void)vtmtxlock(_Sfmutex);
+ for(ff = File; ff; ff = next)
+ { next = ff->next;
+ _tmprmfile(ff->f, SF_CLOSING, NIL(Void_t*), ff->f->disc);
+ }
+ (void)vtmtxunlock(_Sfmutex);
+}
+
+static Sfdisc_t Rmdisc =
+ { NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmprmfile, NIL(Sfdisc_t*) };
+
+#endif /*_tmp_rmfail*/
+
+#if __STD_C
+static int _rmtmp(Sfio_t* f, char* file)
+#else
+static int _rmtmp(f, file)
+Sfio_t* f;
+char* file;
+#endif
+{
+#if _tmp_rmfail /* remove only when stream is closed */
+ reg File_t* ff;
+
+ if(!File)
+ atexit(_rmfiles);
+
+ if(!(ff = (File_t*)malloc(sizeof(File_t)+strlen(file))) )
+ return -1;
+ (void)vtmtxlock(_Sfmutex);
+ ff->f = f;
+ strcpy(ff->name,file);
+ ff->next = File;
+ File = ff;
+ (void)vtmtxunlock(_Sfmutex);
+
+#else /* can remove now */
+ while(sysremovef(file) < 0 && errno == EINTR)
+ errno = 0;
+#endif
+
+ return 0;
+}
+
+#if !_PACKAGE_ast
+#define TMPDFLT "/tmp"
+static char **Tmppath, **Tmpcur;
+
+#if __STD_C
+char** _sfgetpath(char* path)
+#else
+char** _sfgetpath(path)
+char* path;
+#endif
+{ reg char *p, **dirs;
+ reg int n;
+
+ if(!(path = getenv(path)) )
+ return NIL(char**);
+
+ for(p = path, n = 0;;) /* count number of directories */
+ { while(*p == ':')
+ ++p;
+ if(*p == 0)
+ break;
+ n += 1;
+ while(*p && *p != ':') /* skip dir name */
+ ++p;
+ }
+ if(n == 0 || !(dirs = (char**)malloc((n+1)*sizeof(char*))) )
+ return NIL(char**);
+ if(!(p = (char*)malloc(strlen(path)+1)) )
+ { free(dirs);
+ return NIL(char**);
+ }
+ strcpy(p,path);
+ for(n = 0;; ++n)
+ { while(*p == ':')
+ ++p;
+ if(*p == 0)
+ break;
+ dirs[n] = p;
+ while(*p && *p != ':')
+ ++p;
+ if(*p == ':')
+ *p++ = 0;
+ }
+ dirs[n] = NIL(char*);
+
+ return dirs;
+}
+
+#endif /*!_PACKAGE_ast*/
+
+#if __STD_C
+static int _tmpfd(Sfio_t* f)
+#else
+static int _tmpfd(f)
+Sfio_t* f;
+#endif
+{
+ reg char* file;
+ int fd;
+
+#if _PACKAGE_ast
+ if(!(file = pathtemp(NiL,PATH_MAX,NiL,"sf",&fd)))
+ return -1;
+ _rmtmp(f, file);
+ free(file);
+#else
+ int t;
+
+ /* set up path of dirs to create temp files */
+ if(!Tmppath && !(Tmppath = _sfgetpath("TMPPATH")) )
+ { if(!(Tmppath = (char**)malloc(2*sizeof(char*))) )
+ return -1;
+ if(!(file = getenv("TMPDIR")) )
+ file = TMPDFLT;
+ if(!(Tmppath[0] = (char*)malloc(strlen(file)+1)) )
+ { free(Tmppath);
+ Tmppath = NIL(char**);
+ return -1;
+ }
+ strcpy(Tmppath[0],file);
+ Tmppath[1] = NIL(char*);
+ }
+
+ /* set current directory to create this temp file */
+ if(Tmpcur)
+ Tmpcur += 1;
+ if(!Tmpcur || !Tmpcur[0])
+ Tmpcur = Tmppath;
+
+ fd = -1;
+ for(t = 0; t < 10; ++t)
+ { /* compute a random name */
+ static ulong Key, A;
+ if(A == 0 || t > 0) /* get a quasi-random coefficient */
+ { reg int r;
+ A = (ulong)time(NIL(time_t*)) ^ (((ulong)(&t)) >> 3);
+ if(Key == 0)
+ Key = (A >> 16) | ((A&0xffff)<<16);
+ A ^= Key;
+ if((r = (A-1) & 03) != 0) /* Knuth vol.2, page.16, Thm.A */
+ A += 4-r;
+ }
+
+ Key = A*Key + 987654321;
+ file = sfprints("%s/sf%3.3.32lu.%3.3.32lu",
+ Tmpcur[0], (Key>>15)&0x7fff, Key&0x7fff);
+ if(!file)
+ return -1;
+#if _has_oflags
+ if((fd = sysopenf(file,O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY,SF_CREATMODE)) >= 0)
+ break;
+#else
+ if((fd = sysopenf(file,O_RDONLY)) >= 0)
+ { /* file already exists */
+ CLOSE(fd);
+ fd = -1;
+ }
+ else if((fd = syscreatf(file,SF_CREATMODE)) >= 0)
+ { /* reopen for read and write */
+ CLOSE(fd);
+ if((fd = sysopenf(file,O_RDWR)) >= 0)
+ break;
+
+ /* don't know what happened but must remove file */
+ while(sysremovef(file) < 0 && errno == EINTR)
+ errno = 0;
+ }
+#endif /* _has_oflags */
+ }
+ if(fd >= 0)
+ _rmtmp(f, file);
+#endif /* _PACKAGE_ast */
+ return fd;
+}
+
+#if __STD_C
+static int _tmpexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _tmpexcept(f,type,val,disc)
+Sfio_t* f;
+int type;
+Void_t* val;
+Sfdisc_t* disc;
+#endif
+{
+ reg int fd, m;
+ reg Sfio_t* sf;
+ Sfio_t newf, savf;
+ void (*notifyf)_ARG_((Sfio_t*, int, void*));
+
+ NOTUSED(val);
+
+ /* the discipline needs to change only under the following exceptions */
+ if(type != SF_WRITE && type != SF_SEEK &&
+ type != SF_DPUSH && type != SF_DPOP && type != SF_DBUFFER)
+ return 0;
+
+ /* notify function */
+ notifyf = _Sfnotify;
+
+ /* try to create the temp file */
+ SFCLEAR(&newf,NIL(Vtmutex_t*));
+ newf.flags = SF_STATIC;
+ newf.mode = SF_AVAIL;
+
+ if((fd = _tmpfd(f)) < 0 )
+ return -1;
+
+ /* make sure that the notify function won't be called here since
+ we are only interested in creating the file, not the stream */
+ _Sfnotify = 0;
+ sf = sfnew(&newf,NIL(Void_t*),(size_t)SF_UNBOUND,fd,SF_READ|SF_WRITE);
+ _Sfnotify = notifyf;
+ if(!sf)
+ return -1;
+
+ if(newf.mutex) /* don't need a mutex for this stream */
+ { (void)vtmtxclrlock(newf.mutex);
+ (void)vtmtxclose(newf.mutex);
+ newf.mutex = NIL(Vtmutex_t*);
+ }
+
+ /* make sure that new stream has the same mode */
+ if((m = f->flags&(SF_READ|SF_WRITE)) != (SF_READ|SF_WRITE))
+ sfset(sf, ((~m)&(SF_READ|SF_WRITE)), 0);
+ sfset(sf, (f->mode&(SF_READ|SF_WRITE)), 1);
+
+ /* now remake the old stream into the new image */
+ memcpy((Void_t*)(&savf), (Void_t*)f, sizeof(Sfio_t));
+ memcpy((Void_t*)f, (Void_t*)sf, sizeof(Sfio_t));
+ f->push = savf.push;
+ f->pool = savf.pool;
+ f->rsrv = savf.rsrv;
+ f->proc = savf.proc;
+ f->mutex = savf.mutex;
+ f->stdio = savf.stdio;
+
+ if(savf.data)
+ { SFSTRSIZE(&savf);
+ if(!(savf.flags&SF_MALLOC) )
+ (void)sfsetbuf(f,(Void_t*)savf.data,savf.size);
+ if(savf.extent > 0)
+ (void)sfwrite(f,(Void_t*)savf.data,(size_t)savf.extent);
+ (void)sfseek(f,(Sfoff_t)(savf.next - savf.data),SEEK_SET);
+ if((savf.flags&SF_MALLOC) )
+ free((Void_t*)savf.data);
+ }
+
+ /* announce change of status */
+ if(notifyf)
+ (*notifyf)(f, SF_NEW, (void*)((long)f->file));
+
+ f->disc = disc->disc;
+
+ /* erase all traces of newf */
+ newf.data = newf.endb = newf.endr = newf.endw = NIL(uchar*);
+ newf.file = -1;
+ sfclose(&newf);
+
+ return 1;
+}
+
+#if __STD_C
+Sfio_t* sftmp(size_t s)
+#else
+Sfio_t* sftmp(s)
+size_t s;
+#endif
+{
+ Sfio_t* f;
+ static Sfdisc_t Tmpdisc =
+ { NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmpexcept,
+#if _tmp_rmfail
+ &Rmdisc
+#else
+ NIL(Sfdisc_t*)
+#endif
+ };
+
+ /* start with a memory resident stream */
+ if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),s,-1,SF_STRING|SF_READ|SF_WRITE)) )
+ return NIL(Sfio_t*);
+
+ if(s != (size_t)SF_UNBOUND) /* set up a discipline for out-of-bound, etc. */
+ f->disc = &Tmpdisc;
+
+ /* make the file now */
+ if(s == 0 && _tmpexcept(f,SF_DPOP,NIL(Void_t*),f->disc) < 0)
+ { sfclose(f);
+ return NIL(Sfio_t*);
+ }
+
+ return f;
+}
diff --git a/src/lib/libast/sfio/sfungetc.c b/src/lib/libast/sfio/sfungetc.c
new file mode 100644
index 0000000..08ccc6d
--- /dev/null
+++ b/src/lib/libast/sfio/sfungetc.c
@@ -0,0 +1,108 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Push back one byte to a given SF_READ stream
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+static int _uexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _uexcept(f,type,val,disc)
+Sfio_t *f;
+int type;
+Void_t* val;
+Sfdisc_t *disc;
+#endif
+{
+ NOTUSED(val);
+
+ /* hmm! This should never happen */
+ if(disc != _Sfudisc)
+ return -1;
+
+ /* close the unget stream */
+ if(type != SF_CLOSING)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ return 1;
+}
+
+#if __STD_C
+int sfungetc(Sfio_t* f, int c)
+#else
+int sfungetc(f,c)
+Sfio_t* f; /* push back one byte to this stream */
+int c; /* the value to be pushed back */
+#endif
+{
+ reg Sfio_t* uf;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(c < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0))
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* fast handling of the typical unget */
+ if(f->next > f->data && f->next[-1] == (uchar)c)
+ { f->next -= 1;
+ goto done;
+ }
+
+ /* make a string stream for unget characters */
+ if(f->disc != _Sfudisc)
+ { if(!(uf = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND,
+ -1,SF_STRING|SF_READ)))
+ { c = -1;
+ goto done;
+ }
+ _Sfudisc->exceptf = _uexcept;
+ sfdisc(uf,_Sfudisc);
+ SFOPEN(f,0); (void)sfstack(f,uf); SFLOCK(f,0);
+ }
+
+ /* space for data */
+ if(f->next == f->data)
+ { reg uchar* data;
+ if(f->size < 0)
+ f->size = 0;
+ if(!(data = (uchar*)malloc(f->size+16)))
+ { c = -1;
+ goto done;
+ }
+ f->flags |= SF_MALLOC;
+ if(f->data)
+ memcpy((char*)(data+16),(char*)f->data,f->size);
+ f->size += 16;
+ f->data = data;
+ f->next = data+16;
+ f->endb = data+f->size;
+ }
+
+ *--f->next = (uchar)c;
+done:
+ SFOPEN(f,0);
+ SFMTXRETURN(f, c);
+}
diff --git a/src/lib/libast/sfio/sfvprintf.c b/src/lib/libast/sfio/sfvprintf.c
new file mode 100644
index 0000000..3d1a1bd
--- /dev/null
+++ b/src/lib/libast/sfio/sfvprintf.c
@@ -0,0 +1,1445 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* The engine for formatting data.
+** 1. Argument positioning is done in sftable.c so any changes
+** made here should be reflected in sftable.c as well.
+** 2. For internationalization, Sfio only supports I/O of multibyte strings.
+** However, this code does provide minimal support so that Stdio functions
+** such as fwprintf/swprintf can be emulated (see stdvwprintf()).
+**
+** Written by Kiem-Phong Vo.
+*/
+#define HIGHBITI (~((~((uint)0)) >> 1))
+#define HIGHBITL (~((~((Sfulong_t)0)) >> 1))
+
+#define SFFMT_PREFIX (SFFMT_MINUS|SFFMT_SIGN|SFFMT_BLANK)
+
+#define FPRECIS 6 /* default precision for floats */
+
+#if _PACKAGE_ast
+#include <ccode.h>
+#else
+/* characters when using ebcdic or ascii */
+#if _chr_ebcdic
+#define CC_vt 013 /* vertical tab */
+#define CC_esc 047 /* escape */
+#define CC_bel 057 /* bell */
+#else
+#define CC_vt 013 /* vertical tab */
+#define CC_esc 033 /* escape */
+#define CC_bel 007 /* bell */
+#endif /* _chr_ebcdic */
+#endif /* _PACKAGE_ast */
+
+#if __STD_C
+static int chr2str(char* buf, int v)
+#else
+static int chr2str(buf, v)
+char* buf;
+int v;
+#endif
+{
+ if(isprint(v) && v != '\\')
+ { *buf++ = v;
+ return 1;
+ }
+ else
+ { *buf++ = '\\';
+ switch(v)
+ { case CC_bel: *buf++ = 'a'; return 2;
+ case CC_vt: *buf++ = 'v'; return 2;
+ case CC_esc: *buf++ = 'E'; return 2;
+ case '\b': *buf++ = 'b'; return 2;
+ case '\f': *buf++ = 'f'; return 2;
+ case '\n': *buf++ = 'n'; return 2;
+ case '\r': *buf++ = 'r'; return 2;
+ case '\t': *buf++ = 't'; return 2;
+ case '\\': *buf++ = '\\'; return 2;
+ default: *buf++ = '0' + ((v >> 6) & 03);
+ *buf++ = '0' + ((v >> 3) & 07);
+ *buf++ = '0' + ((v >> 0) & 07);
+ return 4;
+ }
+ }
+}
+
+/* On some platform(s), large functions are not compilable.
+** In such a case, the below macro should be defined non-zero so that
+** some in-lined macros will be made smaller, trading time for space.
+*/
+#if !defined(_sffmt_small) && defined(_UTS)
+#define _sffmt_small 1
+#endif
+
+#if __STD_C
+int sfvprintf(Sfio_t* f, const char* form, va_list args)
+#else
+int sfvprintf(f,form,args)
+Sfio_t* f; /* file to print to */
+char* form; /* format to use */
+va_list args; /* arg list if !argf */
+#endif
+{
+ int n, v, w, k, n_s, base, fmt, flags;
+ Sflong_t lv;
+ char *sp, *ssp, *endsp, *ep, *endep;
+ int dot, width, precis, sign, decpt;
+#if _PACKAGE_ast
+ int scale;
+#endif
+ ssize_t size;
+ Sfdouble_t dval;
+ Void_t* valp;
+ char *tls[2], **ls; /* for %..[separ]s */
+ char* t_str; /* stuff between () */
+ ssize_t n_str; /* its length */
+
+ Argv_t argv; /* for extf to return value */
+ Sffmt_t *ft; /* format environment */
+ Fmt_t *fm, *fmstk; /* stack contexts */
+
+ char* oform; /* original format string */
+ va_list oargs; /* original arg list */
+ Fmtpos_t* fp; /* arg position list */
+ int argp, argn; /* arg position and number */
+
+#define SLACK 1024
+ char buf[SF_MAXDIGITS+SLACK], tmp[SF_MAXDIGITS+1], data[SF_GRAIN];
+ int decimal = 0, thousand = 0;
+
+#if _has_multibyte
+ wchar_t* wsp;
+ SFMBDCL(fmbs) /* state of format string */
+ SFMBDCL(mbs) /* state of some string */
+#ifdef mbwidth
+ char* osp;
+ int n_w, wc;
+#endif
+#endif
+
+ /* local io system */
+ int o, n_output;
+#define SMputc(f,c) { if((o = SFFLSBUF(f,c)) >= 0 ) n_output += 1; \
+ else { SFBUF(f); goto done; } \
+ }
+#define SMnputc(f,c,n) { if((o = SFNPUTC(f,c,n)) > 0 ) n_output += 1; \
+ if(o != n) { SFBUF(f); goto done; } \
+ }
+#define SMwrite(f,s,n) { if((o = SFWRITE(f,(Void_t*)s,n)) > 0 ) n_output += o; \
+ if(o != n) { SFBUF(f); goto done; } \
+ }
+#if _sffmt_small /* these macros are made smaller at some performance cost */
+#define SFBUF(f)
+#define SFINIT(f) (n_output = 0)
+#define SFEND(f)
+#define SFputc(f,c) SMputc(f,c)
+#define SFnputc(f,c,n) SMnputc(f,c,n)
+#define SFwrite(f,s,n) SMwrite(f,s,n)
+#else
+ uchar *d, *endd;
+#define SFBUF(f) (d = f->next, endd = f->endb)
+#define SFINIT(f) (SFBUF(f), n_output = 0)
+#define SFEND(f) ((n_output += d - f->next), (f->next = d))
+#define SFputc(f,c) { if(d < endd) { *d++ = (uchar)c; } \
+ else { SFEND(f); SMputc(f,c); SFBUF(f); } \
+ }
+#define SFnputc(f,c,n) { if(d+n <= endd) { while(n--) *d++ = (uchar)(c); } \
+ else { SFEND(f); SMnputc(f,c,n); SFBUF(f); } \
+ }
+#define SFwrite(f,s,n) { if(d+n <= endd) { while(n--) *d++ = (uchar)(*s++); } \
+ else { SFEND(f); SMwrite(f,s,n); SFBUF(f); } \
+ }
+#endif /* _sffmt_small */
+
+ SFMTXDECL(f);
+
+ SFCVINIT(); /* initialize conversion tables */
+
+ SFMTXENTER(f,-1);
+
+ if(!form)
+ SFMTXRETURN(f, -1);
+
+ /* make sure stream is in write mode and buffer is not NULL */
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,0);
+
+ if(!f->data && !(f->flags&SF_STRING))
+ { f->data = f->next = (uchar*)data;
+ f->endb = f->data+sizeof(data);
+ }
+ SFINIT(f);
+
+ tls[1] = NIL(char*);
+
+ fmstk = NIL(Fmt_t*);
+ ft = NIL(Sffmt_t*);
+
+ oform = (char*)form;
+ va_copy(oargs,args);
+ argn = -1;
+ fp = NIL(Fmtpos_t*);
+
+loop_fmt :
+ SFMBCLR(&fmbs); /* clear multibyte states to parse the format string */
+ while((n = *form) )
+ { if(n != '%') /* collect the non-pattern chars */
+ { sp = (char*)form;
+ do
+ { if((n = SFMBLEN(form, &fmbs)) <= 0)
+ { n = 1;
+ SFMBCLR(&fmbs);
+ }
+ } while(*(form += n) && *form != '%');
+
+ n = form-sp;
+ SFwrite(f,sp,n);
+ continue;
+ }
+ else form += 1;
+
+ flags = 0;
+#if _PACKAGE_ast
+ scale = 0;
+#endif
+ size = width = precis = base = n_s = argp = -1;
+ ssp = _Sfdigits;
+ endep = ep = NIL(char*);
+ endsp = sp = buf+(sizeof(buf)-1);
+ t_str = NIL(char*);
+ n_str = dot = 0;
+
+ loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
+ switch((fmt = *form++) )
+ {
+ case '\0':
+ SFputc(f,'%');
+ goto pop_fmt;
+ case '%' :
+ SFputc(f,'%');
+ continue;
+
+ case LEFTP : /* get the type enclosed in balanced parens */
+ t_str = (char*)form;
+ for(v = 1;;)
+ { switch(*form++)
+ {
+ case 0 : /* not balancable, retract */
+ form = t_str;
+ t_str = NIL(char*);
+ n_str = 0;
+ goto loop_flags;
+ case LEFTP : /* increasing nested level */
+ v += 1;
+ continue;
+ case RIGHTP : /* decreasing nested level */
+ if((v -= 1) != 0)
+ continue;
+ if(*t_str != '*' )
+ n_str = (form-1)-t_str;
+ else
+ { t_str = (*_Sffmtintf)(t_str+1,&n);
+ if(*t_str == '$')
+ { if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ { t_str = fp[n].argv.s;
+ n_str = fp[n].ft.size;
+ }
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args,
+ LEFTP, 0, 0, 0,0,0,
+ NIL(char*),0);
+ n = (*ft->extf)
+ (f,(Void_t*)&argv,ft);
+ if(n < 0)
+ goto pop_fmt;
+ if(!(ft->flags&SFFMT_VALUE) )
+ goto t_arg;
+ if((t_str = argv.s) &&
+ (n_str = (int)ft->size) < 0)
+ n_str = strlen(t_str);
+ }
+ else
+ { t_arg:
+ if((t_str = va_arg(args,char*)) )
+ n_str = strlen(t_str);
+ }
+ }
+ goto loop_flags;
+ }
+ }
+
+ case '-' :
+ if(dot == 1)
+ { dot = 0;
+ precis = -1;
+ flags |= SFFMT_CHOP;
+ }
+ else
+ flags = (flags & ~(SFFMT_CENTER|SFFMT_ZERO)) | SFFMT_LEFT;
+ goto loop_flags;
+ case '0' :
+ if(!(flags&(SFFMT_LEFT|SFFMT_CENTER)) )
+ flags |= SFFMT_ZERO;
+ goto loop_flags;
+ case ' ' :
+ if(!(flags&SFFMT_SIGN) )
+ flags |= SFFMT_BLANK;
+ goto loop_flags;
+ case '+' :
+ flags = (flags & ~SFFMT_BLANK) | SFFMT_SIGN;
+ goto loop_flags;
+ case '=' :
+ flags = (flags & ~(SFFMT_LEFT|SFFMT_ZERO)) | SFFMT_CENTER;
+ goto loop_flags;
+ case '#' :
+ flags |= SFFMT_ALTER;
+ goto loop_flags;
+ case QUOTE:
+ SFSETLOCALE(&decimal,&thousand);
+ if(thousand > 0)
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+ case ',':
+ SFSETLOCALE(&decimal,&thousand);
+ if(thousand < 0)
+ thousand = fmt;
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+
+ case '.':
+ dot += 1;
+ if(dot == 1)
+ { /* so base can be defined without setting precis */
+ if(*form != '.' && !(flags & SFFMT_CHOP))
+ precis = 0;
+ }
+ else if(dot == 2)
+ { base = 0; /* for %s,%c */
+ v = form[0] == 'l' ? form[1] : form[0];
+ if(v == 'c' || v == 'C' || v == 's' || v == 'S')
+ goto loop_flags;
+ if(*form && !isalnum(*form))
+ { v = form[1] == 'l' ? form[2] : form[1];
+ if(v == 'c' || v == 'C' || v == 's' || v == 'S')
+ { if(*form == '*')
+ goto do_star;
+ else
+ { base = *form++;
+ goto loop_flags;
+ }
+ }
+ }
+ }
+
+ if(isdigit(*form) )
+ { fmt = *form++;
+ goto dot_size;
+ }
+ else if(*form != '*')
+ goto loop_flags;
+ do_star:
+ form += 1; /* fall thru for '*' */
+ case '*' :
+ form = (*_Sffmtintf)(form,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ v = fp[n].argv.i;
+ else if(ft && ft->extf)
+ { FMTSET(ft, form,args, '.',dot, 0, 0,0,0, NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ fmt = ft->fmt;
+ flags = (flags&~SFFMT_TYPES) | (ft->flags&SFFMT_TYPES);
+ if(ft->flags&SFFMT_VALUE)
+ v = argv.i;
+ else v = (dot <= 2) ? va_arg(args,int) : 0;
+ }
+ else v = dot <= 2 ? va_arg(args,int) : 0;
+ goto dot_set;
+
+ case '1' : case '2' : case '3' :
+ case '4' : case '5' : case '6' :
+ case '7' : case '8' : case '9' :
+ dot_size :
+ for(v = fmt - '0'; isdigit(*form); ++form)
+ v = v*10 + (*form - '0');
+ if(*form == '$')
+ { form += 1;
+ if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )
+ goto pop_fmt;
+ argp = v-1;
+ goto loop_flags;
+ }
+ dot_set :
+ if(dot == 0)
+ { if((width = v) < 0)
+ { width = -width;
+ flags = (flags & ~(SFFMT_CENTER|SFFMT_ZERO)) | SFFMT_LEFT;
+ }
+ }
+ else if(dot == 1)
+ precis = v;
+ else if(dot == 2)
+ base = v;
+ goto loop_flags;
+
+ case 'I' : /* object length */
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
+ if(isdigit(*form) )
+ { for(size = 0, n = *form; isdigit(n); n = *++form)
+ size = size*10 + (n - '0');
+ }
+ else if(*form == '*')
+ { form = (*_Sffmtintf)(form+1,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)))
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp) /* use position list */
+ size = fp[n].argv.i;
+ else if(ft && ft->extf)
+ { FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0,
+ NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ if(ft->flags&SFFMT_VALUE)
+ size = argv.i;
+ else size = va_arg(args,int);
+ }
+ else size = va_arg(args,int);
+ }
+ goto loop_flags;
+
+ case 'l' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'l')
+ { form += 1;
+ flags |= SFFMT_LLONG;
+ }
+ else flags |= SFFMT_LONG;
+ goto loop_flags;
+ case 'h' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'h')
+ { form += 1;
+ flags |= SFFMT_SSHORT;
+ }
+ else flags |= SFFMT_SHORT;
+ goto loop_flags;
+ case 'L' :
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
+ goto loop_flags;
+
+ case 'j' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG;
+ goto loop_flags;
+ case 'z' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG;
+ goto loop_flags;
+ case 't' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG;
+ goto loop_flags;
+ default:
+ break;
+ }
+
+ /* set object size for scalars */
+ if(flags & SFFMT_TYPES)
+ { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
+ { if(flags&SFFMT_LONG)
+ size = sizeof(long);
+ else if(flags&SFFMT_SHORT)
+ size = sizeof(short);
+ else if(flags&SFFMT_SSHORT)
+ size = sizeof(char);
+ else if(flags&SFFMT_TFLAG)
+ size = sizeof(ptrdiff_t);
+ else if(flags&SFFMT_ZFLAG)
+ size = sizeof(size_t);
+ else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
+ size = sizeof(Sflong_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0 ||
+ size == sizeof(Sflong_t)*CHAR_BIT )
+ size = sizeof(Sflong_t);
+ }
+ else if(size < 0)
+ size = sizeof(int);
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT)
+ { if(flags&SFFMT_LDOUBLE)
+ size = sizeof(Sfdouble_t);
+ else if(flags&(SFFMT_LONG|SFFMT_LLONG))
+ size = sizeof(double);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0)
+ size = sizeof(Sfdouble_t);
+ }
+ else if(size < 0)
+ size = sizeof(float);
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ {
+#if _has_multibyte
+ if((flags&SFFMT_LONG) || fmt == 'C')
+ { size = sizeof(wchar_t) > sizeof(int) ?
+ sizeof(wchar_t) : sizeof(int);
+ } else
+#endif
+ if(size < 0)
+ size = sizeof(int);
+ }
+ }
+
+ argp = FP_SET(argp,argn);
+ if(fp)
+ { if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt)
+ fmt = fp[argp].ft.fmt;
+ argv = fp[argp].argv;
+ size = fp[argp].ft.size;
+ }
+ else if(ft && ft->extf ) /* extended processing */
+ { FMTSET(ft, form,args, fmt, size,flags, width,precis,base,
+ t_str,n_str);
+ SFEND(f); SFOPEN(f,0);
+ v = (*ft->extf)(f, (Void_t*)(&argv), ft);
+ SFLOCK(f,0); SFBUF(f);
+
+ if(v < 0) /* no further processing */
+ goto pop_fmt;
+ else if(v > 0) /* extf output v bytes */
+ { n_output += v;
+ continue;
+ }
+ else /* extf did not output */
+ { FMTGET(ft, form,args, fmt, size,flags, width,precis,base);
+
+ if(!(ft->flags&SFFMT_VALUE))
+ goto arg_list;
+ else if(_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT) )
+ { if(size == sizeof(short))
+ { if(_Sftype[fmt]&SFFMT_INT)
+ argv.i = argv.h;
+ else argv.i = argv.uh;
+ }
+ else if(size == sizeof(char))
+ { if(_Sftype[fmt]&SFFMT_INT)
+ argv.i = argv.c;
+ else argv.i = argv.uc;
+ }
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT )
+ { if(size == sizeof(float) )
+ argv.d = argv.f;
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ { if(base < 0)
+ argv.i = (int)argv.c;
+ }
+ }
+ }
+ else
+ { arg_list:
+ switch(_Sftype[fmt])
+ { case SFFMT_INT:
+ case SFFMT_UINT:
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t))
+ argv.ll = va_arg(args, Sflong_t);
+ else
+#endif
+ if(size == sizeof(long) )
+ argv.l = va_arg(args, long);
+ else argv.i = va_arg(args, int);
+ break;
+ case SFFMT_FLOAT:
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t))
+ argv.ld = va_arg(args,Sfdouble_t);
+ else
+#endif
+ argv.d = va_arg(args,double);
+ break;
+ case SFFMT_POINTER:
+ argv.vp = va_arg(args,Void_t*);
+ break;
+ case SFFMT_CHAR:
+ if(base >= 0)
+ argv.s = va_arg(args,char*);
+#if _has_multibyte
+ else if((flags & SFFMT_LONG) || fmt == 'C')
+ { if(sizeof(wchar_t) <= sizeof(uint) )
+ argv.wc = (wchar_t)va_arg(args,uint);
+ else argv.wc = va_arg(args,wchar_t);
+ }
+#endif
+ else argv.i = va_arg(args,int);
+ break;
+ default: /* unknown pattern */
+ break;
+ }
+ }
+
+ switch(fmt) /* PRINTF DIRECTIVES */
+ {
+ default : /* unknown directive */
+ form -= 1;
+ argn -= 1;
+ continue;
+
+ case '!' : /* stacking a new environment */
+ if(!fp)
+ fp = (*_Sffmtposf)(f,oform,oargs,ft,0);
+ else goto pop_fmt;
+
+ if(!argv.ft)
+ goto pop_fmt;
+ if(!argv.ft->form && ft ) /* change extension functions */
+ { if(ft->eventf &&
+ (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ continue;
+ fmstk->ft = ft = argv.ft;
+ }
+ else /* stack a new environment */
+ { if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) )
+ goto done;
+
+ ft = fm->ft = argv.ft;
+ SFMBSET(ft->mbs, &fmbs);
+ if(ft->form)
+ { fm->form = (char*)form; SFMBCPY(&fm->mbs,&fmbs);
+ va_copy(fm->args,args);
+
+ fm->oform = oform;
+ va_copy(fm->oargs,oargs);
+ fm->argn = argn;
+ fm->fp = fp;
+
+ form = ft->form; SFMBCLR(ft->mbs);
+ va_copy(args,ft->args);
+ argn = -1;
+ fp = NIL(Fmtpos_t*);
+ oform = (char*)form;
+ va_copy(oargs,args);
+ }
+ else fm->form = NIL(char*);
+
+ fm->eventf = ft->eventf;
+ fm->next = fmstk;
+ fmstk = fm;
+ }
+ continue;
+
+ case 'S':
+ flags = (flags & ~(SFFMT_TYPES|SFFMT_LDOUBLE)) | SFFMT_LONG;
+ case 's':
+#if _has_multibyte && defined(mbwidth)
+ wc = (flags & SFFMT_LDOUBLE) && mbwide();
+#endif
+ if(base >= 0) /* list of strings */
+ { if(!(ls = argv.sp) || !ls[0])
+ continue;
+ }
+ else
+ { if(!(sp = argv.s))
+ { sp = "(null)";
+ flags &= ~SFFMT_LONG;
+ }
+#if _PACKAGE_ast
+ str_cvt:
+ if(scale)
+ { size = base = -1;
+ flags &= ~SFFMT_LONG;
+ }
+#endif
+ ls = tls; tls[0] = sp;
+ }
+ for(sp = *ls;;)
+ { /* v: number of bytes w: print width of those v bytes */
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { v = 0;
+#ifdef mbwidth
+ w = 0;
+#endif
+ SFMBCLR(&mbs);
+ for(n = 0, wsp = (wchar_t*)sp;; ++wsp, ++n)
+ { if((size >= 0 && n >= size) ||
+ (size < 0 && *wsp == 0) )
+ break;
+ if((n_s = wcrtomb(buf, *wsp, &mbs)) <= 0)
+ break;
+#ifdef mbwidth
+ if(wc)
+ { n_w = mbwidth(*wsp);
+ if(precis >= 0 && (w+n_w) > precis )
+ break;
+ w += n_w;
+ }
+ else
+#endif
+ if(precis >= 0 && (v+n_s) > precis )
+ break;
+ v += n_s;
+ }
+#ifdef mbwidth
+ if(!wc)
+ w = v;
+#endif
+ }
+#ifdef mbwidth
+ else if (wc)
+ { w = 0;
+ SFMBCLR(&mbs);
+ ssp = sp;
+ for(;;)
+ { if((size >= 0 && w >= size) ||
+ (size < 0 && *ssp == 0) )
+ break;
+ osp = ssp;
+ n = mbchar(osp);
+ n_w = mbwidth(n);
+ if(precis >= 0 && (w+n_w) > precis )
+ break;
+ w += n_w;
+ ssp = osp;
+ }
+ v = ssp - sp;
+ }
+#endif
+ else
+#endif
+ { if((v = size) < 0)
+ for(v = 0; v != precis && sp[v]; ++v);
+ if(precis >= 0 && v > precis)
+ v = precis;
+ w = v;
+ }
+
+ if((n = width - w) > 0 && !(flags&SFFMT_LEFT) )
+ { if(flags&SFFMT_CENTER)
+ { n -= (k = n/2);
+ SFnputc(f, ' ', k);
+ }
+ else
+ { SFnputc(f, ' ', n);
+ n = 0;
+ }
+ }
+ if(n < 0 && (flags & SFFMT_CHOP) && width > 0 && precis < 0)
+ {
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { SFMBCLR(&mbs);
+ wsp = (wchar_t*)sp;
+ while(n < 0)
+ {
+#ifdef mbwidth
+ n += mbwidth(*wsp);
+#else
+ n++;
+#endif
+ wsp++;
+ w--;
+ }
+ sp = (char*)wsp;
+ }
+ else if (wc)
+ { SFMBCLR(&mbs);
+ osp = sp;
+ while(n < 0)
+ { ssp = sp;
+ if ((k = mbchar(sp)) <= 0)
+ { sp = ssp;
+ break;
+ }
+#ifdef mbwidth
+ n += mbwidth(k);
+#else
+ n++;
+#endif
+ }
+ v -= (sp - osp);
+ }
+#endif
+ else
+ { sp += -n;
+ v += n;
+ }
+ n = 0;
+ }
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { SFMBCLR(&mbs);
+ for(wsp = (wchar_t*)sp; w > 0; ++wsp, --w)
+ { if((n_s = wcrtomb(buf, *wsp, &mbs)) <= 0)
+ break;
+ sp = buf; SFwrite(f, sp, n_s);
+ }
+ }
+ else
+#endif
+ { SFwrite(f,sp,v); }
+ if(n > 0)
+ { SFnputc(f,' ',n); }
+ if(!(sp = *++ls))
+ break;
+ else if(base > 0)
+ { SFputc(f,base); }
+ }
+ continue;
+
+ case 'C':
+ flags = (flags & ~(SFFMT_TYPES|SFFMT_LDOUBLE)) | SFFMT_LONG;
+ case 'c':
+#if _has_multibyte && defined(mbwidth)
+ wc = (flags & SFFMT_LDOUBLE) && mbwide();
+#endif
+ if(precis <= 0) /* # of times to repeat a character */
+ precis = 1;
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { if(base >= 0)
+ { if(!(wsp = (wchar_t*)argv.s) )
+ continue;
+ for(size = 0; wsp[size]; ++size)
+ ;
+ }
+ else
+ { wsp = &argv.wc;
+ size = 1;
+ }
+ }
+ else
+#endif
+ { if(base >= 0)
+ { if(!(sp = argv.s) )
+ continue;
+ size = strlen(sp);
+ }
+ else
+ { argv.c = (char)(argv.i);
+ sp = &argv.c;
+ size = 1;
+ }
+ }
+
+ while(size > 0)
+ {
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ { SFMBCLR(&mbs);
+ if((n_s = wcrtomb(buf, *wsp++, &mbs)) <= 0)
+ break;
+#ifdef mbwidth
+ if(wc)
+ n_s = mbwidth(*(wsp - 1));
+#endif
+ n = width - precis*n_s; /* padding amount */
+ }
+ else
+#endif
+ if(flags&SFFMT_ALTER)
+ { n_s = chr2str(buf, *sp++);
+ n = width - precis*n_s;
+ }
+ else
+ { fmt = *sp++;
+ n = width - precis;
+ }
+
+ if(n > 0 && !(flags&SFFMT_LEFT) )
+ { if(flags&SFFMT_CENTER)
+ { n -= (k = n/2);
+ SFnputc(f, ' ', k);
+ }
+ else
+ { SFnputc(f, ' ', n);
+ n = 0;
+ }
+ }
+
+ v = precis; /* need this because SFnputc may clear it */
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ { for(; v > 0; --v)
+ { ssp = buf; k = n_s; SFwrite(f,ssp,k); }
+ }
+ else
+#endif
+ if(flags&SFFMT_ALTER)
+ { for(; v > 0; --v)
+ { ssp = buf; k = n_s; SFwrite(f,ssp,k); }
+ }
+ else
+ { SFnputc(f, fmt, v);
+ }
+
+ if(n > 0)
+ { SFnputc(f,' ',n); };
+
+ if((size -= 1) > 0 && base > 0)
+ { SFputc(f,base); }
+ }
+ continue;
+
+ case 'n': /* return current output length */
+ SFEND(f);
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t) )
+ *((Sflong_t*)argv.vp) = (Sflong_t)n_output;
+ else
+#endif
+ if(size == sizeof(long))
+ *((long*)argv.vp) = (long)n_output;
+ else if(size == sizeof(short) )
+ *((short*)argv.vp) = (short)n_output;
+ else if(size == sizeof(uchar) )
+ *((uchar*)argv.vp) = (uchar)n_output;
+ else *((int*)argv.vp) = (int)n_output;
+
+ continue;
+
+ case 'p': /* pointer value */
+ fmt = 'x';
+ base = 16; n_s = 15; n = 4;
+ flags = (flags&~(SFFMT_SIGN|SFFMT_BLANK|SFFMT_ZERO))|SFFMT_ALTER;
+#if _more_void_int
+ lv = (Sflong_t)((Sfulong_t)argv.vp);
+ goto long_cvt;
+#else
+ v = (int)((uint)argv.vp);
+ goto int_cvt;
+#endif
+ case 'o':
+ base = 8; n_s = 7; n = 3;
+ flags &= ~(SFFMT_SIGN|SFFMT_BLANK);
+ goto int_arg;
+ case 'X':
+ ssp = "0123456789ABCDEF";
+ case 'x':
+ base = 16; n_s = 15; n = 4;
+ flags &= ~(SFFMT_SIGN|SFFMT_BLANK);
+ goto int_arg;
+ case 'i':
+#if _PACKAGE_ast
+ if((flags&SFFMT_ALTER) && base < 0)
+ { flags &= ~SFFMT_ALTER;
+ scale = 1024;
+ }
+#endif
+ fmt = 'd';
+ goto d_format;
+ case 'u':
+ flags &= ~(SFFMT_SIGN|SFFMT_BLANK);
+ case 'd':
+ d_format:
+#if _PACKAGE_ast
+ if((flags&SFFMT_ALTER) && base < 0)
+ { flags &= ~SFFMT_ALTER;
+ scale = 1000;
+ }
+#endif
+ if(base < 2 || base > SF_RADIX)
+ base = 10;
+ if((base&(n_s = base-1)) == 0)
+ { if(base < 8)
+ n = base < 4 ? 1 : 2;
+ else if(base < 32)
+ n = base < 16 ? 3 : 4;
+ else n = base < 64 ? 5 : 6;
+ }
+ else n_s = base == 10 ? -1 : 0;
+
+ int_arg:
+#if !_ast_intmax_long || _more_long_int || _more_void_int
+ if(size == sizeof(Sflong_t))
+ { lv = argv.ll;
+ goto long_cvt;
+ }
+ else if(sizeof(long) < sizeof(Sflong_t) && size == sizeof(long))
+ { if(fmt == 'd')
+ lv = (Sflong_t)argv.l;
+ else lv = (Sflong_t)argv.ul;
+ long_cvt:
+#if _PACKAGE_ast
+ if(scale)
+ { sp = fmtscale(lv, scale);
+#if _has_multibyte && defined(mbwidth)
+ wc = 0;
+#endif
+ goto str_cvt;
+ }
+#endif
+ if(lv == 0 && precis == 0)
+ break;
+ if(lv < 0 && fmt == 'd' )
+ { flags |= SFFMT_MINUS;
+ if(lv == HIGHBITL) /* avoid overflow */
+ { lv = (Sflong_t)(HIGHBITL/base);
+ *--sp = _Sfdigits[HIGHBITL -
+ ((Sfulong_t)lv)*base];
+ }
+ else lv = -lv;
+ }
+ if(n_s < 0) /* base 10 */
+ { Sflong_t nv;
+ sfucvt(lv,sp,nv,ssp,Sflong_t,Sfulong_t);
+ }
+ else if(n_s > 0) /* base power-of-2 */
+ { do
+ { *--sp = ssp[lv&n_s];
+ } while((lv = ((Sfulong_t)lv) >> n) );
+ }
+ else /* general base */
+ { do
+ { *--sp = ssp[((Sfulong_t)lv)%base];
+ } while((lv = ((Sfulong_t)lv)/base) );
+ }
+ } else
+#endif
+ if(sizeof(short) < sizeof(int) && size == sizeof(short) )
+ { if(fmt == 'd')
+ v = (int)((short)argv.i);
+ else v = (int)((ushort)argv.i);
+ goto int_cvt;
+ }
+ else if(size == sizeof(char))
+ { if(fmt != 'd')
+ v = (int)((uchar)argv.i);
+ else
+ {
+#if _key_signed
+ v = (int)((signed char)argv.i);
+#else
+ if(argv.i < 0)
+ v = -((int)((char)(-argv.i)));
+ else v = ((int)((char)( argv.i)));
+#endif
+ }
+ goto int_cvt;
+ }
+ else
+ { v = argv.i;
+ int_cvt:
+#if _PACKAGE_ast
+ if(scale)
+ { sp = fmtscale(v, scale);
+#if _has_multibyte && defined(mbwidth)
+ wc = 0;
+#endif
+ goto str_cvt;
+ }
+#endif
+ if(v == 0 && precis == 0)
+ break;
+ if(v < 0 && fmt == 'd' )
+ { flags |= SFFMT_MINUS;
+ if(v == HIGHBITI) /* avoid overflow */
+ { v = (int)(HIGHBITI/base);
+ *--sp = _Sfdigits[HIGHBITI -
+ ((uint)v)*base];
+ }
+ else v = -v;
+ }
+ if(n_s < 0) /* base 10 */
+ { sfucvt(v,sp,n,ssp,int,uint);
+ }
+ else if(n_s > 0) /* base power-of-2 */
+ { do
+ { *--sp = ssp[v&n_s];
+ } while((v = ((uint)v) >> n) );
+ }
+ else /* n_s == 0, general base */
+ { do
+ { *--sp = ssp[((uint)v)%base];
+ } while((v = ((uint)v)/base) );
+ }
+ }
+
+ if(n_s < 0 && (flags&SFFMT_THOUSAND) && (n = endsp-sp) > 3)
+ { if((n %= 3) == 0)
+ n = 3;
+ for(ep = buf+SLACK, endep = ep + n; ; )
+ { while(ep < endep)
+ *ep++ = *sp++;
+ if(sp == endsp)
+ break;
+ if(sp <= endsp-3)
+ *ep++ = thousand;
+ endep = ep+3;
+ }
+ sp = buf+SLACK;
+ endsp = ep;
+ }
+
+ /* zero padding for precision if have room in buffer */
+ if(precis > 0 && (precis -= (endsp-sp)) < (sp-buf)-64)
+ while(precis-- > 0)
+ *--sp = '0';
+
+ if(flags&SFFMT_ALTER) /* prefix */
+ { if(fmt == 'o')
+ { if(*sp != '0')
+ *--sp = '0';
+ }
+ else
+ { if(width > 0 && (flags&SFFMT_ZERO))
+ { /* do 0 padding first */
+ if(fmt == 'x' || fmt == 'X')
+ n = 0;
+ else if(dot < 2)
+ n = width;
+ else n = base < 10 ? 2 : 3;
+ n += (flags&(SFFMT_MINUS|SFFMT_SIGN)) ?
+ 1 : 0;
+ n = width - (n + (endsp-sp));
+ while(n-- > 0)
+ *--sp = '0';
+ }
+ if(fmt == 'x' || fmt == 'X')
+ { *--sp = (char)fmt;
+ *--sp = '0';
+ }
+ else if(dot >= 2)
+ { /* base#value notation */
+ *--sp = '#';
+ if(base < 10)
+ *--sp = (char)('0'+base);
+ else
+ { *--sp = _Sfdec[(base <<= 1)+1];
+ *--sp = _Sfdec[base];
+ }
+ }
+ }
+ }
+
+ break;
+
+ case 'g': case 'G': /* these ultimately become %e or %f */
+ case 'a': case 'A':
+ case 'e': case 'E':
+ case 'f': case 'F':
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t) )
+ { v = SFFMT_LDOUBLE;
+ valp = &argv.ld;
+ dval = argv.ld;
+ }
+ else
+#endif
+ { v = 0;
+ valp = &argv.d;
+ dval = argv.d;
+ }
+
+ if(fmt == 'e' || fmt == 'E' && (v |= SFFMT_UPPER))
+ { v |= SFFMT_EFORMAT;
+ n = (precis = precis < 0 ? FPRECIS : precis)+1;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(n,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+ goto e_format;
+ }
+ else if(fmt == 'f' || fmt == 'F' && (v |= SFFMT_UPPER))
+ { precis = precis < 0 ? FPRECIS : precis;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(precis,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+ goto f_format;
+ }
+ else if(fmt == 'a' || fmt == 'A' && (v |= SFFMT_UPPER))
+ { v |= SFFMT_AFORMAT;
+ if(precis < 0)
+ { if(v & SFFMT_LDOUBLE)
+ precis = 2*(sizeof(Sfdouble_t) - 2);
+ else precis = 2*(sizeof(double) - 2);
+ }
+ n = precis + 1;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(n,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+
+ sp = endsp = buf+1; /* reserve space for sign */
+ *endsp++ = '0';
+ *endsp++ = fmt == 'a' ? 'x' : 'X';
+ if (!isxdigit(*ep))
+ goto infinite;
+ if (base < 0)
+ base = 0;
+ goto a_format;
+ }
+ else /* 'g' or 'G' format */
+ { precis = precis < 0 ? FPRECIS : precis == 0 ? 1 : precis;
+ if(fmt == 'G')
+ v |= SFFMT_UPPER;
+ v |= SFFMT_EFORMAT;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(precis,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+ if(dval == 0.)
+ decpt = 1;
+ else if(*ep == 'I')
+ goto infinite;
+
+ if(!(flags&SFFMT_ALTER))
+ { /* zap trailing 0s */
+ if((n = n_s) > precis)
+ n = precis;
+ while((n -= 1) >= 1 && ep[n] == '0')
+ ;
+ n += 1;
+ }
+ else n = precis;
+
+ if(decpt < -3 || decpt > precis)
+ { precis = n-1;
+ goto e_format;
+ }
+ else
+ { precis = n - decpt;
+ goto f_format;
+ }
+ }
+
+ e_format: /* build the x.yyyy string */
+ if(isalpha(*ep))
+ goto infinite;
+ sp = endsp = buf+1; /* reserve space for sign */
+ if (base <= 0)
+ base = 2;
+ a_format:
+ *endsp++ = *ep ? *ep++ : '0';
+
+ SFSETLOCALE(&decimal,&thousand);
+ if(precis > 0 || (flags&SFFMT_ALTER))
+ *endsp++ = decimal;
+ ssp = endsp;
+ endep = ep+precis;
+ while((*endsp++ = *ep++) && ep <= endep)
+ ;
+ precis -= (endsp -= 1) - ssp;
+
+ /* build the exponent */
+ ep = endep = buf+(sizeof(buf)-1);
+ if(dval != 0.)
+ { if((n = decpt - 1) < 0)
+ n = -n;
+ while(n > 9)
+ { v = n; n /= 10;
+ *--ep = (char)('0' + (v - n*10));
+ }
+ }
+ else n = 0;
+ *--ep = (char)('0' + n);
+ while((endep-ep) < base && ep > (buf+2)) /* at least base digits in exponent */
+ *--ep = '0';
+
+ /* the e/Exponent separator and sign */
+ *--ep = (decpt > 0 || dval == 0.) ? '+' : '-';
+ *--ep = fmt == 'a' ? 'p' : fmt == 'A' ? 'P' :
+ isupper(fmt) ? 'E' : 'e';
+
+ goto end_aefg;
+
+ f_format: /* data before the decimal point */
+ if(isalpha(*ep))
+ {
+ infinite:
+ flags &= ~SFFMT_ZERO;
+ endsp = (sp = ep)+sfslen();
+ ep = endep;
+ precis = 0;
+ goto end_aefg;
+ }
+
+ SFSETLOCALE(&decimal,&thousand);
+ endsp = sp = buf+1; /* save a space for sign */
+ endep = ep+decpt;
+ if(decpt > 3 && (flags&SFFMT_THOUSAND) )
+ { if((n = decpt%3) == 0)
+ n = 3;
+ while(ep < endep && (*endsp++ = *ep++) )
+ { if(--n == 0 && (ep <= endep-3) )
+ { *endsp++ = thousand;
+ n = 3;
+ }
+ }
+ }
+ else
+ { while(ep < endep && (*endsp++ = *ep++))
+ ;
+ }
+ if(endsp == sp)
+ *endsp++ = '0';
+
+ if(precis > 0 || (flags&SFFMT_ALTER))
+ *endsp++ = decimal;
+
+ if((n = -decpt) > 0)
+ { /* output zeros for negative exponent */
+ ssp = endsp + min(n,precis);
+ precis -= n;
+ while(endsp < ssp)
+ *endsp++ = '0';
+ }
+
+ ssp = endsp;
+ endep = ep+precis;
+ while((*endsp++ = *ep++) && ep <= endep)
+ ;
+ precis -= (endsp -= 1) - ssp;
+ ep = endep;
+ end_aefg:
+ flags |= SFFMT_FLOAT;
+ if(sign)
+ flags |= SFFMT_MINUS;
+ break;
+ }
+
+ if(flags == 0 && width <= 0)
+ goto do_output;
+
+ if(flags&SFFMT_PREFIX)
+ fmt = (flags&SFFMT_MINUS) ? '-' : (flags&SFFMT_SIGN) ? '+' : ' ';
+
+ n = (endsp-sp) + (endep-ep) + (precis <= 0 ? 0 : precis) +
+ ((flags&SFFMT_PREFIX) ? 1 : 0);
+ if((v = width-n) <= 0)
+ v = 0;
+ else if(!(flags&SFFMT_ZERO)) /* right padding */
+ { if(flags&SFFMT_LEFT)
+ v = -v;
+ else if(flags&SFFMT_PREFIX) /* blank padding, output prefix now */
+ { *--sp = fmt;
+ flags &= ~SFFMT_PREFIX;
+ }
+ }
+
+ if(flags&SFFMT_PREFIX) /* put out the prefix */
+ { SFputc(f,fmt);
+ if(fmt != ' ')
+ flags |= SFFMT_ZERO;
+ }
+
+ if((n = v) > 0) /* left padding */
+ { v = (flags&SFFMT_ZERO) ? '0' : ' ';
+ SFnputc(f,v,n);
+ }
+
+ if((n = precis) > 0 && !(flags&SFFMT_FLOAT))
+ { /* padding for integer precision */
+ SFnputc(f,'0',n);
+ precis = 0;
+ }
+
+ do_output:
+ if((n = endsp-sp) > 0)
+ SFwrite(f,sp,n);
+
+ if(flags&(SFFMT_FLOAT|SFFMT_LEFT))
+ { /* SFFMT_FLOAT: right padding for float precision */
+ if((n = precis) > 0)
+ SFnputc(f,'0',n);
+
+ /* SFFMT_FLOAT: the exponent of %eE */
+ if((n = endep - (sp = ep)) > 0)
+ SFwrite(f,sp,n);
+
+ /* SFFMT_LEFT: right padding */
+ if((n = -v) > 0)
+ { SFnputc(f,' ',n); }
+ }
+ }
+
+pop_fmt:
+ if(fp)
+ { free(fp);
+ fp = NIL(Fmtpos_t*);
+ }
+ while((fm = fmstk) ) /* pop the format stack and continue */
+ { if(fm->eventf)
+ { if(!form || !form[0])
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),ft);
+ else if((*fm->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ goto loop_fmt;
+ }
+
+ fmstk = fm->next;
+ if((form = fm->form) )
+ { SFMBCPY(&fmbs,&fm->mbs);
+ va_copy(args, fm->args);
+ oform = fm->oform;
+ va_copy(oargs,fm->oargs);
+ argn = fm->argn;
+ fp = fm->fp;
+ }
+ ft = fm->ft;
+ free(fm);
+ if(form && form[0])
+ goto loop_fmt;
+ }
+
+done:
+ if(fp)
+ free(fp);
+ while((fm = fmstk) )
+ { if(fm->eventf)
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft);
+ fmstk = fm->next;
+ free(fm);
+ }
+
+ SFEND(f);
+
+ n = f->next - f->data;
+ if((sp = (char*)f->data) == data)
+ f->endw = f->endr = f->endb = f->data = NIL(uchar*);
+ f->next = f->data;
+
+ if((((flags = f->flags)&SF_SHARE) && !(flags&SF_PUBLIC) ) ||
+ (n > 0 && (sp == data || (flags&SF_LINE) ) ) )
+ (void)SFWRITE(f,(Void_t*)sp,n);
+ else f->next += n;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, n_output);
+}
diff --git a/src/lib/libast/sfio/sfvscanf.c b/src/lib/libast/sfio/sfvscanf.c
new file mode 100644
index 0000000..c0a1a0b
--- /dev/null
+++ b/src/lib/libast/sfio/sfvscanf.c
@@ -0,0 +1,1100 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* The main engine for reading formatted data
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define MAXWIDTH (int)(((uint)~0)>>1) /* max amount to scan */
+
+/*
+ * pull in a private strtold()
+ */
+
+#include "sfstrtof.h"
+
+/* refresh stream buffer - taking care of unseekable/share streams too */
+#if __STD_C
+static void _sfbuf(Sfio_t* f, int* peek)
+#else
+static void _sfbuf(f, peek)
+Sfio_t* f;
+int* peek;
+#endif
+{
+ if(f->next >= f->endb)
+ { if(*peek) /* try peeking for a share stream if possible */
+ { f->mode |= SF_RV;
+ if(SFFILBUF(f,-1) > 0)
+ { f->mode |= SF_PEEK;
+ return;
+ }
+ *peek = 0; /* can't peek, back to normal reads */
+ }
+ (void)SFFILBUF(f,-1);
+ }
+}
+
+/* buffer used during scanning of a double value or a multi-byte
+ character. the fields mirror certain local variables in sfvscanf. */
+typedef struct _scan_s
+{ int error; /* get set by _sfdscan if no value specified */
+ int inp; /* last input character read */
+ int width; /* field width */
+ Sfio_t *f; /* stream being scanned */
+ uchar *d, *endd, *data; /* local buffering system */
+ int peek; /* != 0 if unseekable/share stream */
+ int n_input;/* number of input bytes processed */
+} Scan_t;
+
+/* ds != 0 for scanning double values */
+#define SCinit(sc,ds) ((sc)->inp = (sc)->error = -1, (sc)->f = f, \
+ ((sc)->width = (ds) ? width : -1), \
+ (sc)->d = d, (sc)->endd = endd, (sc)->data = data, \
+ (sc)->peek = peek, (sc)->n_input = n_input)
+#define SCend(sc,ds) (inp = (sc)->inp, f = (sc)->f, \
+ (width = (ds) ? (sc)->width : width), \
+ d = (sc)->d, endd = (sc)->endd, data = (sc)->data, \
+ peek = (sc)->peek, n_input = (sc)->n_input)
+
+#if __STD_C
+static int _scgetc(void* arg, int flag)
+#else
+static int _scgetc(arg, flag)
+void* arg;
+int flag;
+#endif
+{
+ Scan_t *sc = (Scan_t*)arg;
+
+ if (flag)
+ { sc->error = flag;
+ return 0;
+ }
+
+ /* if width >= 0, do not allow to exceed width number of bytes */
+ if(sc->width == 0)
+ { sc->inp = -1;
+ return 0;
+ }
+
+ if(sc->d >= sc->endd) /* refresh local buffer */
+ { sc->n_input += sc->d - sc->data;
+ if(sc->peek)
+ SFREAD(sc->f, sc->data, sc->d - sc->data);
+ else sc->f->next = sc->d;
+
+ _sfbuf(sc->f, &sc->peek);
+ sc->data = sc->d = sc->f->next;
+ sc->endd = sc->f->endb;
+
+ if(sc->d >= sc->endd)
+ { sc->inp = -1;
+ return 0;
+ }
+ }
+
+ if((sc->width -= 1) >= 0) /* from _sfdscan */
+ return (sc->inp = (int)(*sc->d++));
+ else return ((int)(*sc->d++));
+}
+
+/* structure to match characters in a character class */
+typedef struct _accept_s
+{ char ok[SF_MAXCHAR+1];
+ int yes;
+ char *form, *endf;
+#if _has_multibyte
+ wchar_t wc;
+#endif
+} Accept_t;
+
+#if __STD_C
+static char* _sfsetclass(const char* form, Accept_t* ac, int flags)
+#else
+static char* _sfsetclass(form, ac, flags)
+char* form; /* format string */
+Accept_t* ac; /* values of accepted characters */
+int flags; /* SFFMT_LONG for wchar_t */
+#endif
+{
+ int c, endc, n;
+#if _has_multibyte
+ SFMBDCL(mbs)
+#endif
+
+ if(*form == '^') /* complementing this set */
+ { ac->yes = 0;
+ form += 1;
+ }
+ else ac->yes = 1;
+
+ for(c = 0; c <= SF_MAXCHAR; ++c)
+ ac->ok[c] = !ac->yes;
+
+ if(*form == ']' || *form == '-') /* special first char */
+ { ac->ok[*form] = ac->yes;
+ form += 1;
+ }
+ ac->form = (char*)form;
+
+ if(flags&SFFMT_LONG)
+ SFMBCLR(&mbs);
+ for(n = 1; *form != ']'; form += n)
+ { if((c = *((uchar*)form)) == 0)
+ return NIL(char*);
+
+ if(*(form+1) == '-')
+ { endc = *((uchar*)(form+2));
+#if _has_multibyte
+ if(c >= 128 || endc >= 128 ) /* range must be ascii */
+ goto one_char;
+#endif
+ for(; c <= endc; ++c)
+ ac->ok[c] = ac->yes;
+ n = 3;
+ }
+ else
+ { one_char:
+#if _has_multibyte /* true multi-byte chars must be checked differently */
+ if((flags&SFFMT_LONG) && (n = (int)SFMBLEN(form,&mbs)) <= 0)
+ return NIL(char*);
+ if(n == 1)
+#endif
+ ac->ok[c] = ac->yes;
+ }
+ }
+
+ ac->endf = (char*)form;
+ return (char*)(form+1);
+}
+
+#if _has_multibyte
+#if __STD_C
+static int _sfwaccept(wchar_t wc, Accept_t* ac)
+#else
+static int _sfwaccept(wc, ac)
+wchar_t wc;
+Accept_t* ac;
+#endif
+{
+ int endc, c, n;
+ wchar_t fwc;
+ char *form = ac->form;
+ SFMBDCL(mbs)
+
+ SFMBCLR(&mbs);
+ for(n = 1; *form != ']'; form += n)
+ { if((c = *((uchar*)form)) == 0)
+ return 0;
+
+ if(*(form+1) == '-')
+ { endc = *((uchar*)(form+2));
+ if(c >= 128 || endc >= 128 ) /* range must be ascii */
+ goto one_char;
+ n = 3;
+ }
+ else
+ { one_char:
+ if((n = mbrtowc(&fwc, form, ac->endf-form, &mbs)) > 1 &&
+ wc == fwc )
+ return ac->yes;
+ }
+ }
+
+ return !ac->yes;
+}
+
+#if _has_multibyte == 1
+#define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,(Void_t*)(mbs))
+#else
+#define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,NIL(Void_t*))
+#endif
+
+#if __STD_C
+static int _sfgetwc(Scan_t* sc, wchar_t* wc, int fmt, Accept_t* ac, Void_t *mbs)
+#else
+static int _sfgetwc(sc, wc, fmt, ac, mbs)
+Scan_t* sc; /* the scanning handle */
+wchar_t* wc; /* to return a scanned wchar_t */
+int fmt; /* %s, %c, %[ */
+Accept_t* ac; /* accept handle for %[ */
+Void_t* mbs; /* multibyte parsing state */
+#endif
+{
+ int n, v;
+ char b[16]; /* assuming that SFMBMAX <= 16! */
+
+ /* shift left data so that there will be more room to back up on error.
+ this won't help streams with small buffers - c'est la vie! */
+ if(sc->d > sc->f->data && (n = sc->endd - sc->d) > 0 && n < SFMBMAX)
+ { memcpy(sc->f->data, sc->d, n);
+ if(sc->f->endr == sc->f->endb)
+ sc->f->endr = sc->f->data+n;
+ if(sc->f->endw == sc->f->endb)
+ sc->f->endw = sc->f->data+n;
+ sc->f->endb = sc->f->data+n;
+ sc->d = sc->data = sc->f->data;
+ sc->endd = sc->f->endb;
+ if(!mbs) sc->f->endb = sc->endd; /* stop cc's "unused mbs" warning */
+ }
+
+ for(n = 0; n < SFMBMAX; )
+ { if((v = _scgetc((Void_t*)sc, 0)) <= 0)
+ goto no_match;
+ else b[n++] = v;
+
+ if(mbrtowc(wc, b, n, (mbstate_t*)mbs) == (size_t)(-1))
+ goto no_match; /* malformed multi-byte char */
+ else
+ { /* multi-byte char converted successfully */
+ if(fmt == 'c')
+ return 1;
+ else if(fmt == 's')
+ { if(n > 1 || (n == 1 && !isspace(b[0]) ) )
+ return 1;
+ else goto no_match;
+ }
+ else if(fmt == '[')
+ { if((n == 1 && ac->ok[b[0]]) ||
+ (n > 1 && _sfwaccept(*wc,ac)) )
+ return 1;
+ else goto no_match;
+ }
+ else /* if(fmt == '1') match a single wchar_t */
+ { if(*wc == ac->wc)
+ return 1;
+ else goto no_match;
+ }
+ }
+ }
+
+no_match: /* this unget is lossy on a stream with small buffer */
+ if((sc->d -= n) < sc->data)
+ sc->d = sc->data;
+ return 0;
+}
+#endif /*_has_multibyte*/
+
+
+#if __STD_C
+int sfvscanf(Sfio_t* f, reg const char* form, va_list args)
+#else
+int sfvscanf(f,form,args)
+Sfio_t* f; /* file to be scanned */
+reg char* form; /* scanning format */
+va_list args;
+#endif
+{
+ reg int inp, shift, base, width;
+ ssize_t size;
+ int fmt, flags, dot, n_assign, v, n, n_input;
+ char *sp;
+
+ Accept_t acc;
+
+ Argv_t argv;
+ Sffmt_t *ft;
+ Fmt_t *fm, *fmstk;
+
+ Fmtpos_t* fp;
+ char *oform;
+ va_list oargs;
+ int argp, argn;
+
+ int decimal = 0, thousand = 0;
+
+#if _has_multibyte
+ wchar_t wc;
+ SFMBDCL(fmbs)
+ SFMBDCL(mbs)
+#endif
+
+ Void_t* value; /* location to assign scanned value */
+ char* t_str;
+ ssize_t n_str;
+
+ /* local buffering system */
+ Scan_t scd;
+ uchar *d, *endd, *data;
+ int peek;
+#define SFbuf(f) (_sfbuf(f,&peek), (data = d = f->next), (endd = f->endb) )
+#define SFlen(f) (d - data)
+#define SFinit(f) ((peek = f->extent < 0 && (f->flags&SF_SHARE)), SFbuf(f) )
+#define SFend(f) ((n_input += SFlen(f)), \
+ (peek ? SFREAD(f,(Void_t*)data,SFlen(f)) : ((f->next = d),0)) )
+#define SFgetc(f,c) ((c) = (d < endd || (SFend(f), SFbuf(f), d < endd)) ? \
+ (int)(*d++) : -1 )
+#define SFungetc(f,c) (d -= 1)
+
+ SFMTXDECL(f);
+
+ SFCVINIT(); /* initialize conversion tables */
+
+ SFMTXENTER(f,-1);
+
+ if(!form || f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ SFinit(f); /* initialize local buffering system */
+
+ n_assign = n_input = 0; inp = -1;
+
+ fmstk = NIL(Fmt_t*);
+ ft = NIL(Sffmt_t*);
+
+ fp = NIL(Fmtpos_t*);
+ argn = -1;
+ oform = (char*)form;
+ va_copy(oargs,args);
+
+ SFSETLOCALE(&decimal, &thousand);
+
+loop_fmt:
+ SFMBCLR(&fmbs);
+ while((fmt = *form++))
+ { if(fmt != '%')
+ { if(isspace(fmt))
+ { if(fmt != '\n' || !(f->flags&SF_LINE))
+ fmt = -1;
+ for(;;)
+ { if(SFgetc(f,inp) < 0 || inp == fmt)
+ goto loop_fmt;
+ else if(!isspace(inp))
+ { SFungetc(f,inp);
+ goto loop_fmt;
+ }
+ }
+ }
+ else
+ { match_1:
+#if _has_multibyte
+ if((n = (int)mbrtowc(&wc,form-1,SFMBMAX,&fmbs)) <= 0)
+ goto pop_fmt;
+ if(n > 1)
+ { acc.wc = wc;
+ SCinit(&scd,0); SFMBCLR(&mbs);
+ v = SFgetwc(&scd, &wc, '1', &acc, &mbs);
+ SCend(&scd,0);
+ if(v == 0)
+ goto pop_fmt;
+ form += n-1;
+ }
+ else
+#endif
+ if(SFgetc(f,inp) != fmt)
+ { if(inp < 0)
+ goto done;
+ SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ }
+ continue;
+ }
+
+ if(*form == '%')
+ { form += 1;
+ do SFgetc(f,inp); while(isspace(inp)); /* skip starting blanks */
+ SFungetc(f,inp);
+ goto match_1;
+ }
+
+ if(*form == '\0')
+ goto pop_fmt;
+
+ if(*form == '*')
+ { flags = SFFMT_SKIP;
+ form += 1;
+ }
+ else flags = 0;
+
+ /* matching some pattern */
+ base = 10; size = -1;
+ width = dot = 0;
+ t_str = NIL(char*); n_str = 0;
+ value = NIL(Void_t*);
+ argp = -1;
+
+ loop_flags: /* LOOP FOR FLAGS, WIDTH, BASE, TYPE */
+ switch((fmt = *form++) )
+ {
+ case LEFTP : /* get the type which is enclosed in balanced () */
+ t_str = (char*)form;
+ for(v = 1;;)
+ { switch(*form++)
+ {
+ case 0 : /* not balanceable, retract */
+ form = t_str;
+ t_str = NIL(char*);
+ n_str = 0;
+ goto loop_flags;
+ case LEFTP : /* increasing nested level */
+ v += 1;
+ continue;
+ case RIGHTP : /* decreasing nested level */
+ if((v -= 1) != 0)
+ continue;
+ if(*t_str != '*' )
+ n_str = (form-1) - t_str;
+ else
+ { t_str = (*_Sffmtintf)(t_str+1,&n);
+ if(*t_str == '$')
+ { if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ { t_str = fp[n].argv.s;
+ n_str = fp[n].ft.size;
+ }
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args,
+ LEFTP, 0, 0, 0,0,0,
+ NIL(char*),0);
+ n = (*ft->extf)
+ (f,(Void_t*)&argv,ft);
+ if(n < 0)
+ goto pop_fmt;
+ if(!(ft->flags&SFFMT_VALUE) )
+ goto t_arg;
+ if((t_str = argv.s) &&
+ (n_str = (int)ft->size) < 0)
+ n_str = strlen(t_str);
+ }
+ else
+ { t_arg:
+ if((t_str = va_arg(args,char*)) )
+ n_str = strlen(t_str);
+ }
+ }
+ goto loop_flags;
+ }
+ }
+
+ case '#' : /* alternative format */
+ flags |= SFFMT_ALTER;
+ goto loop_flags;
+
+ case '.' : /* width & base */
+ dot += 1;
+ if(isdigit(*form))
+ { fmt = *form++;
+ goto dot_size;
+ }
+ else if(*form == '*')
+ { form = (*_Sffmtintf)(form+1,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ v = fp[n].argv.i;
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args, '.',dot, 0, 0,0,0,
+ NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ if(ft->flags&SFFMT_VALUE)
+ v = argv.i;
+ else v = (dot <= 2) ? va_arg(args,int) : 0;
+ }
+ else v = (dot <= 2) ? va_arg(args,int) : 0;
+ if(v < 0)
+ v = 0;
+ goto dot_set;
+ }
+ else goto loop_flags;
+
+ case '0' : case '1' : case '2' : case '3' : case '4' :
+ case '5' : case '6' : case '7' : case '8' : case '9' :
+ dot_size :
+ for(v = fmt-'0'; isdigit(*form); ++form)
+ v = v*10 + (*form - '0');
+
+ if(*form == '$')
+ { form += 1;
+ if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)) )
+ goto pop_fmt;
+ argp = v-1;
+ goto loop_flags;
+ }
+
+ dot_set :
+ if(dot == 0 || dot == 1)
+ width = v;
+ else if(dot == 2)
+ base = v;
+ goto loop_flags;
+
+ case 'I' : /* object size */
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
+ if(isdigit(*form))
+ { for(size = 0, n = *form; isdigit(n); n = *++form)
+ size = size*10 + (n - '0');
+ }
+ else if(*form == '*')
+ { form = (*_Sffmtintf)(form+1,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)))
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp) /* use position list */
+ size = fp[n].argv.i;
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0,
+ NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ if(ft->flags&SFFMT_VALUE)
+ size = argv.i;
+ else size = va_arg(args,int);
+ }
+ else size = va_arg(args,int);
+ }
+ goto loop_flags;
+
+ case 'l' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'l')
+ { form += 1;
+ flags |= SFFMT_LLONG;
+ }
+ else flags |= SFFMT_LONG;
+ goto loop_flags;
+ case 'h' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'h')
+ { form += 1;
+ flags |= SFFMT_SSHORT;
+ }
+ else flags |= SFFMT_SHORT;
+ goto loop_flags;
+ case 'L' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_LDOUBLE;
+ goto loop_flags;
+ case 'j' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG;
+ goto loop_flags;
+ case 'z' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG;
+ goto loop_flags;
+ case 't' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG;
+ goto loop_flags;
+ case QUOTE :
+ if(thousand > 0)
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+ }
+
+ /* set object size for scalars */
+ if(flags & SFFMT_TYPES)
+ { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
+ { if(flags&SFFMT_LONG)
+ size = sizeof(long);
+ else if(flags&SFFMT_SHORT)
+ size = sizeof(short);
+ else if(flags&SFFMT_SSHORT)
+ size = sizeof(char);
+ else if(flags&SFFMT_TFLAG)
+ size = sizeof(ptrdiff_t);
+ else if(flags&SFFMT_ZFLAG)
+ size = sizeof(size_t);
+ else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
+ size = sizeof(Sflong_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0 ||
+ size == sizeof(Sflong_t)*CHAR_BIT )
+ size = sizeof(Sflong_t);
+ }
+ else if(size < 0)
+ size = sizeof(int);
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT)
+ { if(flags&(SFFMT_LONG|SFFMT_LLONG))
+ size = sizeof(double);
+ else if(flags&SFFMT_LDOUBLE)
+ size = sizeof(Sfdouble_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0)
+ size = sizeof(Sfdouble_t);
+ }
+ else if(size < 0)
+ size = sizeof(float);
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ {
+#if _has_multibyte
+ if((flags&SFFMT_LONG) || fmt == 'C')
+ { size = sizeof(wchar_t) > sizeof(int) ?
+ sizeof(wchar_t) : sizeof(int);
+ } else
+#endif
+ if(size < 0)
+ size = sizeof(int);
+ }
+ }
+
+ argp = FP_SET(argp,argn);
+ if(fp)
+ { if(!(fp[argp].ft.flags&SFFMT_SKIP) )
+ { n_assign += 1;
+ value = fp[argp].argv.vp;
+ size = fp[argp].ft.size;
+ if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt)
+ fmt = fp[argp].ft.fmt;
+ }
+ else flags |= SFFMT_SKIP;
+ }
+ else if(ft && ft->extf)
+ { FMTSET(ft, form,args, fmt, size,flags, width,0,base, t_str,n_str);
+ SFend(f); SFOPEN(f,0);
+ v = (*ft->extf)(f, (Void_t*)&argv, ft);
+ SFLOCK(f,0); SFbuf(f);
+
+ if(v < 0)
+ goto pop_fmt;
+ else if(v > 0) /* extf comsumed v input bytes */
+ { n_input += v;
+ if(!(ft->flags&SFFMT_SKIP) )
+ n_assign += 1;
+ continue;
+ }
+ else /* if(v == 0): extf did not use input stream */
+ { FMTGET(ft, form,args, fmt, size, flags, width,n,base);
+
+ if((ft->flags&SFFMT_VALUE) && !(ft->flags&SFFMT_SKIP) )
+ value = argv.vp;
+ }
+ }
+
+ if(_Sftype[fmt] == 0) /* unknown pattern */
+ goto pop_fmt;
+
+ if(fmt == '!')
+ { if(!fp)
+ fp = (*_Sffmtposf)(f,oform,oargs,ft,1);
+ else goto pop_fmt;
+
+ if(!(argv.ft = va_arg(args,Sffmt_t*)) )
+ continue;
+ if(!argv.ft->form && ft ) /* change extension functions */
+ { if(ft->eventf &&
+ (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ continue;
+ fmstk->ft = ft = argv.ft;
+ }
+ else /* stack a new environment */
+ { if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) )
+ goto done;
+
+ ft = fm->ft = argv.ft;
+ SFMBSET(ft->mbs, &fmbs);
+ if(ft->form)
+ { fm->form = (char*)form; SFMBCPY(&fm->mbs,&fmbs);
+ va_copy(fm->args,args);
+
+ fm->oform = oform;
+ va_copy(fm->oargs,oargs);
+ fm->argn = argn;
+ fm->fp = fp;
+
+ form = ft->form; SFMBCLR(ft->mbs);
+ va_copy(args,ft->args);
+ argn = -1;
+ fp = NIL(Fmtpos_t*);
+ oform = (char*)form;
+ va_copy(oargs,args);
+ }
+ else fm->form = NIL(char*);
+
+ fm->eventf = ft->eventf;
+ fm->next = fmstk;
+ fmstk = fm;
+ }
+ continue;
+ }
+
+ /* get the address to assign value */
+ if(!value && !(flags&SFFMT_SKIP) )
+ value = va_arg(args,Void_t*);
+
+ if(fmt == 'n') /* return length of consumed input */
+ {
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t) )
+ *((Sflong_t*)value) = (Sflong_t)(n_input+SFlen(f));
+ else
+#endif
+ if(size == sizeof(long) )
+ *((long*)value) = (long)(n_input+SFlen(f));
+ else if(size == sizeof(short) )
+ *((short*)value) = (short)(n_input+SFlen(f));
+ else if(size == sizeof(uchar))
+ *((uchar*)value) = (uchar)(n_input+SFlen(f));
+ else *((int*)value) = (int)(n_input+SFlen(f));
+ continue;
+ }
+
+ /* if get here, start scanning input */
+ if(width == 0)
+ width = fmt == 'c' ? 1 : MAXWIDTH;
+
+ /* define the first input character */
+ if(fmt == 'c' || fmt == '[' || fmt == 'C' )
+ SFgetc(f,inp);
+ else
+ { do { SFgetc(f,inp); }
+ while(isspace(inp)); /* skip starting blanks */
+ }
+ if(inp < 0)
+ goto done;
+
+ if(_Sftype[fmt] == SFFMT_FLOAT)
+ { SFungetc(f,inp); SCinit(&scd,1);
+ argv.ld = _sfdscan((Void_t*)(&scd), _scgetc);
+ SCend(&scd,1);
+
+ if(scd.error >= 0)
+ { if(inp >= 0)
+ SFungetc(f, inp);
+ goto pop_fmt;
+ }
+
+ if(value)
+ {
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t))
+ *((Sfdouble_t*)value) = argv.ld;
+ else
+#endif
+ if(size == sizeof(double))
+ *((double*)value) = (double)argv.ld;
+ else *((float*)value) = (float)argv.ld;
+
+ n_assign += 1;
+ }
+ }
+ else if(_Sftype[fmt] == SFFMT_UINT || fmt == 'p')
+ { if(inp == '-')
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ else goto int_cvt;
+ }
+ else if(_Sftype[fmt] == SFFMT_INT)
+ { int_cvt:
+ if(inp == '-' || inp == '+')
+ { if(inp == '-')
+ flags |= SFFMT_MINUS;
+ while(--width > 0 && SFgetc(f,inp) >= 0)
+ if(!isspace(inp))
+ break;
+ }
+ if(inp < 0)
+ goto done;
+
+ if(fmt == 'o')
+ base = 8;
+ else if(fmt == 'x' || fmt == 'X' || fmt == 'p')
+ base = 16;
+ else if(fmt == 'i' && inp == '0') /* self-described data */
+ { base = 8;
+ if(width > 1) /* peek to see if it's a base-16 */
+ { if(SFgetc(f,inp) >= 0)
+ { if(inp == 'x' || inp == 'X')
+ base = 16;
+ SFungetc(f,inp);
+ }
+ inp = '0';
+ }
+ }
+
+ /* now convert */
+ argv.lu = 0;
+ if(base == 16)
+ { sp = (char*)_Sfcv36;
+ shift = 4;
+ if(sp[inp] >= 16)
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ if(inp == '0' && --width > 0)
+ { /* skip leading 0x or 0X */
+ if(SFgetc(f,inp) >= 0 &&
+ (inp == 'x' || inp == 'X') && --width > 0)
+ SFgetc(f,inp);
+ }
+ if(inp >= 0 && sp[inp] < 16)
+ goto base_shift;
+ }
+ else if(base == 10)
+ { for(n = v = 0;; )
+ { /* fast base 10 conversion */
+#define TEN(x) (((x) << 3) + ((x) << 1) )
+ if (inp >= '0' && inp <= '9')
+ { argv.lu = TEN(argv.lu) + (inp-'0');
+ n += 1;
+ }
+ else if(inp == thousand)
+ { if((v && n != 3) || (!v && n > 3) )
+ break;
+ v = 1; n = 0;
+ }
+ else break;
+ if((width -= 1) <= 0 || SFgetc(f,inp) < 0)
+ break;
+ }
+ if (!n && !v)
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+
+ if(fmt == 'i' && inp == '#' && !(flags&SFFMT_ALTER) )
+ { base = (int)argv.lu;
+ if(base < 2 || base > SF_RADIX)
+ goto pop_fmt;
+ argv.lu = 0;
+ sp = (char*)(base <= 36 ? _Sfcv36 : _Sfcv64);
+ if(--width > 0 &&
+ SFgetc(f,inp) >= 0 && sp[inp] < base)
+ goto base_conv;
+ }
+ }
+ else
+ { /* other bases */
+ sp = (char*)(base <= 36 ? _Sfcv36 : _Sfcv64);
+ if(base < 2 || base > SF_RADIX || sp[inp] >= base)
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+
+ base_conv: /* check for power of 2 conversions */
+ if((base & ~(base-1)) == base)
+ { if(base < 8)
+ shift = base < 4 ? 1 : 2;
+ else if(base < 32)
+ shift = base < 16 ? 3 : 4;
+ else shift = base < 64 ? 5 : 6;
+
+ base_shift: do
+ { argv.lu = (argv.lu << shift) + sp[inp];
+ } while(--width > 0 &&
+ SFgetc(f,inp) >= 0 && sp[inp] < base);
+ }
+ else
+ { do
+ { argv.lu = (argv.lu * base) + sp[inp];
+ } while(--width > 0 &&
+ SFgetc(f,inp) >= 0 && sp[inp] < base);
+ }
+ }
+
+ if(flags&SFFMT_MINUS)
+ argv.ll = -argv.ll;
+
+ if(value)
+ { n_assign += 1;
+
+ if(fmt == 'p')
+#if _more_void_int
+ *((Void_t**)value) = (Void_t*)((ulong)argv.lu);
+#else
+ *((Void_t**)value) = (Void_t*)((uint)argv.lu);
+#endif
+#if !_ast_intmax_long
+ else if(size == sizeof(Sflong_t))
+ *((Sflong_t*)value) = argv.ll;
+#endif
+ else if(size == sizeof(long))
+ { if(fmt == 'd' || fmt == 'i')
+ *((long*)value) = (long)argv.ll;
+ else *((ulong*)value) = (ulong)argv.lu;
+ }
+ else if(size == sizeof(short))
+ { if(fmt == 'd' || fmt == 'i')
+ *((short*)value) = (short)argv.ll;
+ else *((ushort*)value) = (ushort)argv.lu;
+ }
+ else if(size == sizeof(char) )
+ { if(fmt == 'd' || fmt == 'i')
+ *((char*)value) = (char)argv.ll;
+ else *((uchar*)value) = (uchar)argv.lu;
+ }
+ else
+ { if(fmt == 'd' || fmt == 'i')
+ *((int*)value) = (int)argv.ll;
+ else *((uint*)value) = (uint)argv.lu;
+ }
+ }
+ }
+ else if(fmt == 'C' || fmt == 'S')
+ { fmt = fmt == 'C' ? 'c' : 's';
+ flags = (flags & ~SFFMT_TYPES) | SFFMT_LONG;
+ goto do_string;
+ }
+ else if(fmt == 's' || fmt == 'c' || fmt == '[' )
+ { do_string:
+ if(value)
+ { if(size < 0)
+ size = MAXWIDTH;
+ if(fmt != 'c')
+ size -= 1;
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ argv.ws = (wchar_t*)value;
+ else
+#endif
+ argv.s = (char*)value;
+ }
+ else size = 0;
+
+ if(fmt == '[' && !(form = _sfsetclass(form,&acc,flags)) )
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+
+ n = 0; /* count number of scanned characters */
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ { SFungetc(f,inp); SCinit(&scd,0); SFMBCLR(&mbs);
+ for(; width > 0; --width)
+ { if(SFgetwc(&scd,&wc,fmt,&acc,&mbs) == 0)
+ break;
+ if((n += 1) <= size)
+ *argv.ws++ = wc;
+ }
+ SCend(&scd,0);
+ }
+ else
+#endif
+
+ if(fmt == 's')
+ { do
+ { if(isspace(inp))
+ break;
+ if((n += 1) <= size)
+ *argv.s++ = inp;
+ } while(--width > 0 && SFgetc(f,inp) >= 0);
+ }
+ else if(fmt == 'c')
+ { do
+ { if((n += 1) <= size)
+ *argv.s++ = inp;
+ } while(--width > 0 && SFgetc(f,inp) >= 0);
+ }
+ else /* if(fmt == '[') */
+ { do
+ { if(!acc.ok[inp])
+ { if(n > 0 || (flags&SFFMT_ALTER) )
+ break;
+ else
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ }
+ if((n += 1) <= size)
+ *argv.s++ = inp;
+ } while(--width > 0 && SFgetc(f,inp) >= 0);
+ }
+
+ if(value && (n > 0 || fmt == '[') )
+ { n_assign += 1;
+ if(fmt != 'c' && size >= 0)
+ {
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ *argv.ws = 0;
+ else
+#endif
+ *argv.s = 0;
+ }
+ }
+ }
+
+ if(width > 0 && inp >= 0)
+ SFungetc(f,inp);
+ }
+
+pop_fmt:
+ if(fp)
+ { free(fp);
+ fp = NIL(Fmtpos_t*);
+ }
+ while((fm = fmstk) ) /* pop the format stack and continue */
+ { if(fm->eventf)
+ { if(!form || !form[0])
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),ft);
+ else if((*fm->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ goto loop_fmt;
+ }
+
+ fmstk = fm->next;
+ if((form = fm->form) )
+ { SFMBCPY(&fmbs,&fm->mbs);
+ va_copy(args, fm->args);
+ oform = fm->oform;
+ va_copy(oargs,fm->oargs);
+ argn = fm->argn;
+ fp = fm->fp;
+ }
+ ft = fm->ft;
+ free(fm);
+ if(form && form[0])
+ goto loop_fmt;
+ }
+
+done:
+ if(fp)
+ free(fp);
+ while((fm = fmstk) )
+ { if(fm->eventf)
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft);
+ fmstk = fm->next;
+ free(fm);
+ }
+
+ SFend(f);
+
+ SFOPEN(f,0);
+
+ if(n_assign == 0 && inp < 0)
+ n_assign = -1;
+
+ SFMTXRETURN(f,n_assign);
+}
diff --git a/src/lib/libast/sfio/sfwalk.c b/src/lib/libast/sfio/sfwalk.c
new file mode 100644
index 0000000..7019863
--- /dev/null
+++ b/src/lib/libast/sfio/sfwalk.c
@@ -0,0 +1,67 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Walk streams and run operations on them
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfwalk(Sfwalk_f walkf, Void_t* data, int type)
+#else
+int sfwalk(walkf, data, type)
+Sfwalk_f walkf; /* return <0: stop, >=0: continue */
+Void_t* data;
+int type; /* walk streams with all given flags */
+#endif
+{
+ Sfpool_t *p;
+ Sfio_t *f;
+ int n, rv;
+
+ /* truly initializing std-streams before walking */
+ if(sfstdin->mode & SF_INIT)
+ _sfmode(sfstdin, (sfstdin->mode & SF_RDWR), 0);
+ if(sfstdout->mode & SF_INIT)
+ _sfmode(sfstdout, (sfstdout->mode & SF_RDWR), 0);
+ if(sfstderr->mode & SF_INIT)
+ _sfmode(sfstderr, (sfstderr->mode & SF_RDWR), 0);
+
+ for(rv = 0, p = &_Sfpool; p; p = p->next)
+ { for(n = 0; n < p->n_sf; )
+ { f = p->sf[n];
+
+ if(type != 0 && (f->_flags&type) != type )
+ continue; /* not in the interested set */
+
+ if((rv = (*walkf)(f, data)) < 0)
+ return rv;
+
+ if(p->sf[n] == f) /* move forward to next stream */
+ n += 1;
+ /* else - a sfclose() was done on current stream */
+ }
+ }
+
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfwr.c b/src/lib/libast/sfio/sfwr.c
new file mode 100644
index 0000000..9f1c0f9
--- /dev/null
+++ b/src/lib/libast/sfio/sfwr.c
@@ -0,0 +1,252 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write data with discipline.
+** In the case of a string stream, this is used mainly to extend
+** the buffer. However, this is done here so that exception handling
+** is done uniformly across all stream types.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* hole preserving writes */
+#if __STD_C
+static ssize_t sfoutput(Sfio_t* f, char* buf, size_t n)
+#else
+static ssize_t sfoutput(f,buf,n)
+Sfio_t* f;
+char* buf;
+size_t n;
+#endif
+{ reg char *sp, *wbuf, *endbuf;
+ reg ssize_t s, w, wr;
+
+ s = w = 0;
+ wbuf = buf;
+ endbuf = buf+n;
+ while(n > 0)
+ { if((ssize_t)n < _Sfpage) /* no hole possible */
+ { buf += n;
+ s = n = 0;
+ }
+ else while((ssize_t)n >= _Sfpage)
+ { /* see if a hole of 0's starts here */
+ sp = buf+1;
+ if(buf[0] == 0 && buf[_Sfpage-1] == 0)
+ { /* check byte at a time until int-aligned */
+ while(((ulong)sp)%sizeof(int))
+ { if(*sp != 0)
+ goto chk_hole;
+ sp += 1;
+ }
+
+ /* check using int to speed up */
+ while(sp < endbuf)
+ { if(*((int*)sp) != 0)
+ goto chk_hole;
+ sp += sizeof(int);
+ }
+
+ /* check the remaining bytes */
+ if(sp > endbuf)
+ { sp -= sizeof(int);
+ while(sp < endbuf)
+ { if(*sp != 0)
+ goto chk_hole;
+ sp += 1;
+ }
+ }
+ }
+
+ chk_hole:
+ if((s = sp-buf) >= _Sfpage) /* found a hole */
+ break;
+
+ /* skip a dirty page */
+ n -= _Sfpage;
+ buf += _Sfpage;
+ }
+
+ /* write out current dirty pages */
+ if(buf > wbuf)
+ { if((ssize_t)n < _Sfpage)
+ { buf = endbuf;
+ n = s = 0;
+ }
+ if((wr = syswritef(f->file,wbuf,buf-wbuf)) > 0)
+ { w += wr;
+ f->bits &= ~SF_HOLE;
+ }
+ if(wr != (buf-wbuf))
+ break;
+ wbuf = buf;
+ }
+
+ /* seek to a rounded boundary within the hole */
+ if(s >= _Sfpage)
+ { s = (s/_Sfpage)*_Sfpage;
+ if(SFSK(f,(Sfoff_t)s,SEEK_CUR,NIL(Sfdisc_t*)) < 0)
+ break;
+ w += s;
+ n -= s;
+ wbuf = (buf += s);
+ f->bits |= SF_HOLE;
+
+ if(n > 0)
+ { /* next page must be dirty */
+ s = (ssize_t)n <= _Sfpage ? 1 : _Sfpage;
+ buf += s;
+ n -= s;
+ }
+ }
+ }
+
+ return w > 0 ? w : -1;
+}
+
+#if __STD_C
+ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+ssize_t sfwr(f,buf,n,disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ reg ssize_t w;
+ reg Sfdisc_t* dc;
+ reg int local, oerrno;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,(ssize_t)(-1));
+
+ GETLOCAL(f,local);
+ if(!local && !(f->bits&SF_DCDOWN)) /* an external user's call */
+ { if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0 )
+ SFMTXRETURN(f, (ssize_t)(-1));
+ if(f->next > f->data && SFSYNC(f) < 0 )
+ SFMTXRETURN(f, (ssize_t)(-1));
+ }
+
+ for(;;)
+ { /* stream locked by sfsetfd() */
+ if(!(f->flags&SF_STRING) && f->file < 0)
+ SFMTXRETURN(f,(ssize_t)0);
+
+ /* clear current error states */
+ f->flags &= ~(SF_EOF|SF_ERROR);
+
+ dc = disc;
+ if(f->flags&SF_STRING) /* just asking to extend buffer */
+ w = n + (f->next - f->data);
+ else
+ { /* warn that a write is about to happen */
+ SFDISC(f,dc,writef);
+ if(dc && dc->exceptf && (f->flags&SF_IOCHECK) )
+ { reg int rv;
+ if(local)
+ SETLOCAL(f);
+ if((rv = _sfexcept(f,SF_WRITE,n,dc)) > 0)
+ n = rv;
+ else if(rv < 0)
+ { f->flags |= SF_ERROR;
+ SFMTXRETURN(f, rv);
+ }
+ }
+
+ if(f->extent >= 0)
+ { /* make sure we are at the right place to write */
+ if(f->flags&SF_APPENDWR)
+ { if(f->here != f->extent || (f->flags&SF_SHARE))
+ { f->here = SFSK(f,(Sfoff_t)0,SEEK_END,dc);
+ f->extent = f->here;
+ }
+ }
+ else if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC))
+ f->here = SFSK(f,f->here,SEEK_SET,dc);
+ }
+
+ oerrno = errno;
+ errno = 0;
+
+ if(dc && dc->writef)
+ { SFDCWR(f,buf,n,dc,w);
+ }
+ else if(SFISNULL(f))
+ w = n;
+ else if(f->flags&SF_WHOLE)
+ goto do_write;
+ else if((ssize_t)n >= _Sfpage &&
+ !(f->flags&(SF_SHARE|SF_APPENDWR)) &&
+ f->here == f->extent && (f->here%_Sfpage) == 0)
+ { if((w = sfoutput(f,(char*)buf,n)) <= 0)
+ goto do_write;
+ }
+ else
+ {
+ do_write:
+ if((w = syswritef(f->file,buf,n)) > 0)
+ f->bits &= ~SF_HOLE;
+ }
+
+ if(errno == 0)
+ errno = oerrno;
+
+ if(w > 0)
+ { if(!(f->bits&SF_DCDOWN) )
+ { if((f->flags&(SF_APPENDWR|SF_PUBLIC)) && f->extent >= 0 )
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc);
+ else f->here += w;
+ if(f->extent >= 0 && f->here > f->extent)
+ f->extent = f->here;
+ }
+
+ SFMTXRETURN(f, (ssize_t)w);
+ }
+ }
+
+ if(local)
+ SETLOCAL(f);
+ switch(_sfexcept(f,SF_WRITE,w,dc))
+ {
+ case SF_ECONT :
+ goto do_continue;
+ case SF_EDONE :
+ w = local ? 0 : w;
+ SFMTXRETURN(f, (ssize_t)w);
+ case SF_EDISC :
+ if(!local && !(f->flags&SF_STRING))
+ goto do_continue;
+ /* else fall thru */
+ case SF_ESTACK :
+ SFMTXRETURN(f, (ssize_t)(-1));
+ }
+
+ do_continue:
+ for(dc = f->disc; dc; dc = dc->disc)
+ if(dc == disc)
+ break;
+ disc = dc;
+ }
+}
diff --git a/src/lib/libast/sfio/sfwrite.c b/src/lib/libast/sfio/sfwrite.c
new file mode 100644
index 0000000..170c863
--- /dev/null
+++ b/src/lib/libast/sfio/sfwrite.c
@@ -0,0 +1,171 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write data out to the file system
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n)
+#else
+ssize_t sfwrite(f,buf,n)
+Sfio_t* f; /* write to this stream. */
+Void_t* buf; /* buffer to be written. */
+size_t n; /* number of bytes. */
+#endif
+{
+ reg uchar *s, *begs, *next;
+ reg ssize_t w;
+ reg int local;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (ssize_t)(-1));
+
+ GETLOCAL(f,local);
+
+ if(!buf)
+ SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) );
+
+ /* release peek lock */
+ if(f->mode&SF_PEEK)
+ { if(!(f->mode&SF_WRITE) && (f->flags&SF_RDWR) != SF_RDWR)
+ SFMTXRETURN(f, (ssize_t)(-1));
+
+ if((uchar*)buf != f->next &&
+ (!f->rsrv || f->rsrv->data != (uchar*)buf) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+
+ f->mode &= ~SF_PEEK;
+
+ if(f->mode&SF_PKRD)
+ { /* read past peeked data */
+ char buf[16];
+ reg ssize_t r;
+
+ for(w = n; w > 0; )
+ { if((r = w) > sizeof(buf))
+ r = sizeof(buf);
+ if((r = sysreadf(f->file,buf,r)) <= 0)
+ { n -= w;
+ break;
+ }
+ else w -= r;
+ }
+
+ f->mode &= ~SF_PKRD;
+ f->endb = f->data + n;
+ f->here += n;
+ }
+
+ if((f->mode&SF_READ) && f->proc)
+ f->next += n;
+ }
+
+ s = begs = (uchar*)buf;
+ for(;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0 )
+ { w = s > begs ? s-begs : -1;
+ SFMTXRETURN(f,w);
+ }
+
+ SFLOCK(f,local);
+
+ w = f->endb - f->next;
+
+ if(s == f->next) /* after sfreserve */
+ { if(w > (ssize_t)n)
+ w = (ssize_t)n;
+ f->next = (s += w);
+ n -= w;
+ break;
+ }
+
+ /* attempt to create space in buffer */
+ if(w == 0 || ((f->flags&SF_WHOLE) && w < (ssize_t)n) )
+ { if(f->flags&SF_STRING) /* extend buffer */
+ { (void)SFWR(f, s, n-w, f->disc);
+ if((w = f->endb - f->next) < (ssize_t)n)
+ { if(!(f->flags&SF_STRING)) /* maybe sftmp */
+ { if(f->next > f->data)
+ goto fls_buf;
+ }
+ else if(w == 0)
+ break;
+ }
+ }
+ else if(f->next > f->data)
+ { fls_buf:
+ (void)SFFLSBUF(f, -1);
+ if((w = f->endb - f->next) < (ssize_t)n &&
+ (f->flags&SF_WHOLE) && f->next > f->data )
+ break;
+ }
+ }
+
+ if(!(f->flags&SF_STRING) && f->next == f->data &&
+ (((f->flags&SF_WHOLE) && w <= n) || SFDIRECT(f,n)) )
+ { /* bypass buffering */
+ if((w = SFWR(f,s,n,f->disc)) <= 0 )
+ break;
+ }
+ else
+ { if(w > (ssize_t)n)
+ w = (ssize_t)n;
+ if(w <= 0) /* no forward progress possible */
+ break;
+ memmove(f->next, s, w);
+ f->next += w;
+ }
+
+ s += w;
+ if((n -= w) <= 0)
+ break;
+ }
+
+ /* always flush buffer for share streams */
+ if(f->extent < 0 && (f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) )
+ (void)SFFLSBUF(f,-1);
+
+ /* check to see if buffer should be flushed */
+ else if(n == 0 && (f->flags&SF_LINE) && !(f->flags&SF_STRING))
+ { if((ssize_t)(n = f->next-f->data) > (w = s-begs))
+ n = w;
+ if(n > 0 && n < HIFORLINE)
+ { for(next = f->next-1; n > 0; --n, --next)
+ { if(*next == '\n')
+ { n = HIFORLINE;
+ break;
+ }
+ }
+ }
+ if(n >= HIFORLINE)
+ (void)SFFLSBUF(f,-1);
+ }
+
+ SFOPEN(f,local);
+
+ w = s-begs;
+ SFMTXRETURN(f,w);
+}
diff --git a/src/lib/libast/sfio/vthread.h b/src/lib/libast/sfio/vthread.h
new file mode 100644
index 0000000..4030958
--- /dev/null
+++ b/src/lib/libast/sfio/vthread.h
@@ -0,0 +1,219 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _VTHREAD_H
+#define _VTHREAD_H 1
+
+#define VTHREAD_VERSION 20001201L
+
+/* Header for the Vthread library.
+** Note that the macro vt_threaded may be defined
+** outside of vthread.h to suppress threading.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com
+*/
+
+#include <ast_common.h>
+#include <errno.h>
+
+/* ast doesn't do threads yet */
+#if _PACKAGE_ast && !defined(vt_threaded)
+#define vt_threaded 0
+#endif
+
+#if !defined(vt_threaded) || (defined(vt_threaded) && vt_threaded == 1)
+#define _may_use_threads 1
+#else
+#define _may_use_threads 0
+#endif
+#undef vt_threaded
+
+#if _may_use_threads && !defined(vt_threaded) && _hdr_pthread
+#define vt_threaded 1
+#include <pthread.h>
+typedef pthread_mutex_t _vtmtx_t;
+typedef pthread_once_t _vtonce_t;
+typedef pthread_t _vtself_t;
+typedef pthread_t _vtid_t;
+typedef pthread_attr_t _vtattr_t;
+
+#if !defined(PTHREAD_ONCE_INIT) && defined(pthread_once_init)
+#define PTHREAD_ONCE_INIT pthread_once_init
+#endif
+
+#endif
+
+#if _may_use_threads && !defined(vt_threaded) && _WIN32
+#define vt_threaded 1
+#include <windows.h>
+typedef CRITICAL_SECTION _vtmtx_t;
+typedef int _vtonce_t;
+typedef HANDLE _vtself_t;
+typedef DWORD _vtid_t;
+typedef SECURITY_ATTRIBUTES _vtattr_t;
+#endif
+
+#ifndef vt_threaded
+#define vt_threaded 0
+#endif
+
+/* common attributes for various structures */
+#define VT_RUNNING 000000001 /* thread is running */
+#define VT_SUSPENDED 000000002 /* thread is suspended */
+#define VT_WAITED 000000004 /* thread has been waited */
+#define VT_FREE 000010000 /* object can be freed */
+#define VT_INIT 000020000 /* object was initialized */
+#define VT_BITS 000030007 /* bits that we care about */
+
+/* directives for vtset() */
+#define VT_STACK 1 /* set stack size */
+
+typedef struct _vtmutex_s Vtmutex_t;
+typedef struct _vtonce_s Vtonce_t;
+typedef struct _vthread_s Vthread_t;
+
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+#ifndef EBUSY
+#define EBUSY 16
+#endif
+#ifndef EDEADLK
+#define EDEADLK 45
+#endif
+#ifndef EPERM
+#define EPERM 1
+#endif
+
+_BEGIN_EXTERNS_
+
+extern Vthread_t* vtopen _ARG_((Vthread_t*, int));
+extern int vtclose _ARG_((Vthread_t*));
+extern int vtset _ARG_((Vthread_t*, int, Void_t*));
+extern int vtrun _ARG_((Vthread_t*, void*(*)(void*), void*));
+extern int vtkill _ARG_((Vthread_t*));
+extern int vtwait _ARG_((Vthread_t*));
+
+extern int vtonce _ARG_((Vtonce_t*, void(*)() ));
+
+extern Vtmutex_t* vtmtxopen _ARG_((Vtmutex_t*, int));
+extern int vtmtxclose _ARG_((Vtmutex_t*));
+extern int vtmtxlock _ARG_((Vtmutex_t*));
+extern int vtmtxtrylock _ARG_((Vtmutex_t*));
+extern int vtmtxunlock _ARG_((Vtmutex_t*));
+extern int vtmtxclrlock _ARG_((Vtmutex_t*));
+
+extern Void_t* vtstatus _ARG_((Vthread_t*));
+extern int vterror _ARG_((Vthread_t*));
+extern int vtmtxerror _ARG_((Vtmutex_t*));
+extern int vtonceerror _ARG_((Vtonce_t*));
+
+_END_EXTERNS_
+
+#if vt_threaded
+
+/* mutex structure */
+struct _vtmutex_s
+{ _vtmtx_t lock;
+ int count;
+ _vtid_t owner;
+ int state;
+ int error;
+};
+
+/* structure for states of thread */
+struct _vthread_s
+{ _vtself_t self; /* self-handle */
+ _vtid_t id; /* thread id */
+ _vtattr_t attrs; /* attributes */
+ size_t stack; /* stack size */
+ int state; /* execution state */
+ int error; /* error status */
+ Void_t* exit; /* exit value */
+};
+
+/* structure for exactly once execution */
+struct _vtonce_s
+{ int done;
+ _vtonce_t once;
+ int error;
+};
+
+#if _WIN32
+#define VTONCE_INITDATA {0, 0}
+#else
+#define VTONCE_INITDATA {0, PTHREAD_ONCE_INIT }
+#endif
+
+#define vtstatus(vt) ((vt)->exit)
+#define vterror(vt) ((vt)->error)
+#define vtmtxerror(mtx) ((mtx)->error)
+#define vtonceerror(once) ((once)->error)
+
+#endif /*vt_threaded*/
+
+/* fake structures and functions */
+#if !vt_threaded
+struct _vtmutex_s
+{ int error;
+};
+struct _vtattr_s
+{ int error;
+};
+struct _vthread_s
+{ int error;
+};
+struct _vtonce_s
+{ int error;
+};
+
+typedef int _vtmtx_t;
+typedef int _vtonce_t;
+typedef int _vtself_t;
+typedef int _vtid_t;
+typedef int _vtattr_t;
+
+#define VTONCE_INITDATA {0}
+
+#define vtopen(vt,flgs) ((Vthread_t*)0)
+#define vtclose(vt) (-1)
+#define vtkill(vt) (-1)
+#define vtwait(vt) (-1)
+#define vtrun(vt,fn,arg) (-1)
+
+#define vtset(vt,t,v) (-1)
+#define vtonce(on,fu) (-1)
+
+#define vtmtxopen(mtx,flgs) ((Vtmutex_t*)0)
+#define vtmtxclose(mtx) (-1)
+#define vtmtxlock(mtx) (-1)
+#define vtmtxtrylock(mtx) (-1)
+#define vtmtxunlock(mtx) (-1)
+#define vtmtxclrlock(mtx) (-1)
+
+#define vtstatus(vt) ((Void_t*)0)
+#define vterror(vt) (0)
+#define vtmtxerror(mtx) (0)
+#define vtonceerror(once) (0)
+
+#endif /*!vt_threaded*/
+
+#endif /*_VTHREAD_H*/