1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#ifndef _SFHDR_H
23#define _SFHDR_H	1
24#if !defined(_BLD_sfio) && !defined(_BLD_stdio)
25#define _BLD_sfio	1
26#endif
27
28/*	Internal definitions for sfio.
29**	Written by Kiem-Phong Vo
30*/
31
32#define _next		next
33#define _endw		endw
34#define _endr		endr
35#define _endb		endb
36#define _push		push
37#define _flags		flags
38#define _file		file
39#define _data		data
40#define _size		size
41#define _val		val
42
43#include	"FEATURE/sfio"
44#include	"FEATURE/mmap"
45
46/* define va_list, etc. before including sfio_t.h (sfio.h) */
47#if !_PACKAGE_ast
48
49/* some systems don't know large files */
50#if defined(_NO_LARGEFILE64_SOURCE) || _mips == 2 /* || __hppa */
51#undef _NO_LARGEFILE64_SOURCE
52#define _NO_LARGEFILE64_SOURCE	1
53#undef	_LARGEFILE64_SOURCE
54#undef	_LARGEFILE_SOURCE
55#endif
56
57#if !_NO_LARGEFILE64_SOURCE && _typ_off64_t && _lib_lseek64 && _lib_stat64
58#undef	_LARGEFILE64_SOURCE
59#undef	_LARGEFILE_SOURCE
60#undef	_FILE_OFFSET_BITS
61#define _LARGEFILE64_SOURCE	1	/* enabling the *64 stuff */
62#define _LARGEFILE_SOURCE	1
63#endif
64
65#if _hdr_stdarg
66#include	<stdarg.h>
67#else
68#include	<varargs.h>
69#endif
70#include	"FEATURE/common"
71#if !__STD_C
72#define const
73#endif
74#endif /* !_PACKAGE_ast */
75
76#include	"sfio_t.h"
77
78/* note that the macro vt_threaded has effect on vthread.h */
79#include	<vthread.h>
80
81/* file system info */
82#if _PACKAGE_ast
83
84#include	<ast.h>
85#include	<ast_time.h>
86#include	<ast_tty.h>
87#include	<ls.h>
88
89/* ast always provides multibyte handling */
90#undef _hdr_wchar
91#undef _lib_mbrtowc
92#undef _lib_wcrtomb
93#define _hdr_wchar	1
94#define _lib_mbrtowc	1
95#define _lib_wcrtomb	1
96
97#if _mem_st_blksize_stat
98#define _stat_blksize	1
99#endif
100
101#if _lib_localeconv && _hdr_locale
102#define _lib_locale	1
103#endif
104
105#define sfoff_t		off_t
106#define sfstat_t	struct stat
107#define sysclosef	close
108#define syscreatf	creat
109#define sysdupf		dup
110#define sysfcntlf	fcntl
111#define sysfstatf	fstat
112#define sysftruncatef	ftruncate
113#define syslseekf	lseek
114#define sysmmapf	mmap
115#define sysmunmapf	munmap
116#define sysopenf	open
117#define syspipef	pipe
118#define sysreadf	read
119#define sysremovef	remove
120#define sysstatf	stat
121#define syswritef	write
122
123#else /*!_PACKAGE_ast*/
124
125/* when building the binary compatibility package, a number of header files
126   are not needed and they may get in the way so we remove them here.
127*/
128#if _SFBINARY_H
129#undef  _hdr_time
130#undef  _sys_time
131#undef  _sys_stat
132#undef  _hdr_stat
133#undef  _hdr_filio
134#undef  _sys_filio
135#undef  _lib_poll
136#undef  _stream_peek
137#undef  _socket_peek
138#undef  _hdr_vfork
139#undef  _sys_vfork
140#undef  _lib_vfork
141#undef  _hdr_values
142#undef  _hdr_math
143#undef  _sys_mman
144#undef  _hdr_mman
145#undef  _sys_ioctl
146#endif
147
148#if _hdr_stdlib
149#include	<stdlib.h>
150#endif
151
152#if _hdr_string
153#include	<string.h>
154#endif
155
156#if _hdr_time
157#include	<time.h>
158#endif
159#if _sys_time
160#include	<sys/time.h>
161#endif
162
163#if _sys_stat
164#include	<sys/stat.h>
165#else
166#if _hdr_stat
167#include	<stat.h>
168#ifndef _sys_stat
169#define	_sys_stat	1
170#endif
171#endif
172#endif /*_sys_stat*/
173
174#ifndef _sys_stat
175#define _sys_stat	0
176#endif
177
178#include	<fcntl.h>
179
180#ifndef F_SETFD
181#ifndef FIOCLEX
182#if _hdr_filio
183#include	<filio.h>
184#else
185#if _sys_filio
186#include	<sys/filio.h>
187#endif /*_sys_filio*/
188#endif /*_hdr_filio*/
189#endif /*_FIOCLEX*/
190#endif /*F_SETFD*/
191
192#if _hdr_unistd
193#include	<unistd.h>
194#endif
195
196#if !_LARGEFILE64_SOURCE	/* turn off the *64 stuff */
197#undef	_typ_off64_t
198#undef	_typ_struct_stat64
199#undef	_lib_creat64
200#undef	_lib_open64
201#undef	_lib_close64
202#undef	_lib_stat64
203#undef	_lib_fstat64
204#undef	_lib_ftruncate64
205#undef	_lib_lseek64
206#undef	_lib_mmap64
207#undef	_lib_munmap64
208#endif /*!_LARGEFILE64_SOURCE */
209
210/* see if we can use memory mapping for io */
211#if _LARGEFILE64_SOURCE && !_lib_mmap64
212#undef _mmap_worthy
213#endif
214#if !_mmap_worthy
215#undef _hdr_mman
216#undef _sys_mman
217#endif
218#if _hdr_mman
219#include	<mman.h>
220#endif
221#if _sys_mman
222#include	<sys/mman.h>
223#endif
224
225/* standardize system calls and types dealing with files */
226#if _typ_off64_t
227#define sfoff_t		off64_t
228#else
229#define sfoff_t		off_t
230#endif
231#if _typ_struct_stat64
232#define sfstat_t	struct stat64
233#else
234#define sfstat_t	struct stat
235#endif
236#if _lib_lseek64
237#define syslseekf	lseek64
238#else
239#define syslseekf	lseek
240#endif
241#if _lib_stat64
242#define sysstatf	stat64
243#else
244#define sysstatf	stat
245#endif
246#if _lib_fstat64
247#define sysfstatf	fstat64
248#else
249#define sysfstatf	fstat
250#endif
251#if _lib_mmap64
252#define sysmmapf	mmap64
253#else
254#define sysmmapf	mmap
255#endif
256#if _lib_munmap64
257#define sysmunmapf	munmap64
258#else
259#define sysmunmapf	munmap
260#endif
261#if _lib_open64
262#define sysopenf	open64
263#else
264#define sysopenf	open
265#endif
266#if _lib_creat64
267#define syscreatf	creat64
268#else
269#define syscreatf	creat
270#endif
271#if _lib_close64
272#define sysclosef	close64
273#else
274#define sysclosef	close
275#endif
276#if _lib_ftruncate64
277#undef _lib_ftruncate
278#define _lib_ftruncate	1
279#define sysftruncatef	ftruncate64
280#endif
281#if !_lib_ftruncate64 && _lib_ftruncate
282#define sysftruncatef	ftruncate
283#endif
284#if _lib_remove
285#define sysremovef	remove
286#else
287#define sysremovef	unlink
288#endif
289
290#define sysreadf	read
291#define syswritef	write
292#define syspipef	pipe
293#define sysdupf		dup
294#define sysfcntlf	fcntl
295
296#endif /*_PACKAGE_ast*/
297
298#if !_mmap_worthy
299#undef MAP_TYPE
300#endif
301
302#include	"FEATURE/float"
303
304#include	<errno.h>
305#include	<ctype.h>
306
307/* deal with multi-byte character and string conversions */
308#if _PACKAGE_ast
309
310#include	<wchar.h>
311
312#define _has_multibyte		1
313
314#define SFMBMAX			mbmax()
315#define SFMBCPY(to,fr)		memcpy((to), (fr), sizeof(mbstate_t))
316#define SFMBCLR(mb)		memset((mb), 0,  sizeof(mbstate_t))
317#define SFMBSET(lhs,v)		(lhs = (v))
318#define SFMBLEN(s,mb)		mbsize(s)
319#define SFMBDCL(ms)		mbstate_t ms;
320
321#else
322
323#if _hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc
324#define _has_multibyte		1	/* Xopen-compliant	*/
325#if _typ___va_list && !defined(__va_list)
326#define __va_list	va_list
327#endif
328#include	<wchar.h>
329#define SFMBCPY(to,fr)		memcpy((to), (fr), sizeof(mbstate_t))
330#define SFMBCLR(mb)		memset((mb), 0,  sizeof(mbstate_t))
331#define SFMBSET(lhs,v)		(lhs = (v))
332#define SFMBDCL(mb)		mbstate_t mb;
333#define SFMBLEN(s,mb)		mbrtowc(NIL(wchar_t*), (s), SFMBMAX, (mb) )
334#endif /*_hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc*/
335
336#if !_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb
337#define _has_multibyte		2	/* no shift states	*/
338#include	<wchar.h>
339#undef mbrtowc
340#define mbrtowc(wp,s,n,mb)	mbtowc(wp, s, n)
341#undef wcrtomb
342#define wcrtomb(s,wc,mb)	wctomb(s, wc)
343#define SFMBCPY(to,fr)
344#define SFMBCLR(mb)
345#define SFMBSET(lhs,v)
346#define SFMBDCL(mb)
347#define SFMBLEN(s,mb)		mbrtowc(NIL(wchar_t*), (s), SFMBMAX, (mb) )
348#endif /*!_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb*/
349
350#ifdef MB_CUR_MAX
351#define SFMBMAX			MB_CUR_MAX
352#else
353#define SFMBMAX			sizeof(Sflong_t)
354#endif
355
356#endif /* _PACKAGE_ast */
357
358#if !_has_multibyte
359#define _has_multibyte		0	/* no multibyte support	*/
360#define SFMBCPY(to,fr)
361#define SFMBCLR(mb)
362#define SFMBSET(lhs,v)
363#define SFMBDCL(mb)
364#define SFMBLEN(s,mb)		(*(s) ? 1 : 0)
365#endif /* _has_multibyte */
366
367/* dealing with streams that might be accessed concurrently */
368#if vt_threaded
369
370#define SFMTXdecl(ff,_mf_)	Sfio_t* _mf_ = (ff)
371#define SFMTXbegin(ff,_mf_,rv) \
372	{	if((ff)->_flags&SF_MTSAFE) \
373		{	(_mf_) = (ff); \
374			if(sfmutex((ff), SFMTX_LOCK) != 0) return(rv); \
375			if(_Sfnotify) \
376			{	(*_Sfnotify)((_mf_), SF_MTACCESS, (Void_t*)(&(ff)) ); \
377				if(!(ff)) (ff) = (_mf_); \
378			} \
379		} \
380	}
381#define SFMTXend(ff,_mf_) \
382	{	if((ff)->_flags&SF_MTSAFE) \
383		{	if(_Sfnotify) \
384				(*_Sfnotify)((_mf_), SF_MTACCESS, NIL(Void_t*) ); \
385			sfmutex((ff), SFMTX_UNLOCK); \
386			(ff) = (_mf_); \
387		} \
388	}
389
390#define SFONCE()		(_Sfdone ? 0 : vtonce(_Sfonce,_Sfoncef))
391
392#define SFMTXLOCK(f)		(((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_LOCK) : 0)
393#define SFMTXUNLOCK(f)		(((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_UNLOCK) : 0)
394
395#define SFMTXDECL(ff)		SFMTXdecl((ff), _mtxf1_)
396#define SFMTXBEGIN(ff,v) 	{ SFMTXbegin((ff), _mtxf1_, (v) ); }
397#define SFMTXEND(ff)		{ SFMTXend(ff, _mtxf1_); }
398#define SFMTXENTER(ff,v) 	{ if(!(ff)) return(v); SFMTXBEGIN((ff), (v)); }
399#define SFMTXRETURN(ff,v)	{ SFMTXEND(ff); return(v); }
400
401#define SFMTXDECL2(ff)		SFMTXdecl((ff), _mtxf2_)
402#define SFMTXBEGIN2(ff,v) 	{ SFMTXbegin((ff), _mtxf2_, (v) ); }
403#define SFMTXEND2(ff)		{ SFMTXend((ff), _mtxf2_); }
404
405#define POOLMTXLOCK(p)		( vtmtxlock(&(p)->mutex) )
406#define POOLMTXUNLOCK(p)	( vtmtxunlock(&(p)->mutex) )
407#define POOLMTXENTER(p)		{ POOLMTXLOCK(p); }
408#define POOLMTXRETURN(p,rv)	{ POOLMTXUNLOCK(p); return(rv); }
409
410#else /*!vt_threaded*/
411
412#undef SF_MTSAFE /* no need to worry about thread-safety */
413#define SF_MTSAFE		0
414
415#define SFONCE()		/*(0)*/
416
417#define SFMTXLOCK(f)		/*(0)*/
418#define SFMTXUNLOCK(f)		/*(0)*/
419
420#define	SFMTXDECL(ff)		/*(0)*/
421#define SFMTXBEGIN(ff,v) 	/*(0)*/
422#define SFMTXEND(ff)		/*(0)*/
423#define SFMTXENTER(ff,v)	{ if(!(ff)) return(v); }
424#define SFMTXRETURN(ff,v)	{ return(v); }
425
426#define SFMTXDECL2(ff)		/*(0)*/
427#define SFMTXBEGIN2(ff,v) 	/*(0)*/
428#define SFMTXEND2(ff)		/*(0)*/
429
430#define POOLMTXLOCK(p)
431#define POOLMTXUNLOCK(p)
432#define POOLMTXENTER(p)
433#define POOLMTXRETURN(p,v)	{ return(v); }
434
435#endif /*vt_threaded*/
436
437
438/* functions for polling readiness of streams */
439#if _lib_select
440#undef _lib_poll
441#if _sys_select
442#include	<sys/select.h>
443#endif
444#else
445#if _lib_poll_fd_1 || _lib_poll_fd_2
446#define _lib_poll	1
447#endif
448#endif /*_lib_select_*/
449
450#if _lib_poll
451#include	<poll.h>
452
453#if _lib_poll_fd_1
454#define SFPOLL(pfd,n,tm)	poll((pfd),(ulong)(n),(tm))
455#else
456#define SFPOLL(pfd,n,tm)	poll((ulong)(n),(pfd),(tm))
457#endif
458#endif /*_lib_poll*/
459
460#if _stream_peek
461#include	<stropts.h>
462#endif
463
464#if _socket_peek
465#include	<sys/socket.h>
466#endif
467
468/* to test for executable access mode of a file */
469#ifndef X_OK
470#define X_OK	01
471#endif
472
473/* alternative process forking */
474#if _lib_vfork && !defined(fork) && !defined(__sparc) && !defined(__sparc__)
475#if _hdr_vfork
476#include	<vfork.h>
477#endif
478#if _sys_vfork
479#include	<sys/vfork.h>
480#endif
481#define fork	vfork
482#endif
483
484/* to get rid of pesky compiler warnings */
485#if __STD_C
486#define NOTUSED(x)	(void)(x)
487#else
488#define NOTUSED(x)	(&x,1)
489#endif
490
491/* Private flags in the "bits" field */
492#define SF_MMAP		00000001	/* in memory mapping mode		*/
493#define SF_BOTH		00000002	/* both read/write			*/
494#define SF_HOLE		00000004	/* a hole of zero's was created		*/
495#define SF_NULL		00000010	/* stream is /dev/null			*/
496#define SF_SEQUENTIAL	00000020	/* sequential access			*/
497#define SF_JUSTSEEK	00000040	/* just did a sfseek			*/
498#define SF_PRIVATE	00000100	/* private stream to Sfio, no mutex	*/
499#define SF_ENDING	00000200	/* no re-io on interrupts at closing	*/
500#define SF_WIDE		00000400	/* in wide mode - stdio only		*/
501#define SF_PUTR		00001000	/* in sfputr()				*/
502
503/* "bits" flags that must be cleared in sfclrlock */
504#define SF_TMPBITS	00170000
505#define SF_DCDOWN	00010000	/* recurse down the discipline stack	*/
506
507#define SF_WCFORMAT	00020000	/* wchar_t formatting - stdio only	*/
508#if _has_multibyte
509#define SFWCSET(f)	((f)->bits |= SF_WCFORMAT)
510#define SFWCGET(f,v)	(((v) = (f)->bits & SF_WCFORMAT), ((f)->bits &= ~SF_WCFORMAT) )
511#else
512#define SFWCSET(f)
513#define SFWCGET(f,v)
514#endif
515
516#define SF_MVSIZE	00040000	/* f->size was reset in sfmove()	*/
517#define SFMVSET(f)	(((f)->size *= SF_NMAP), ((f)->bits |= SF_MVSIZE) )
518#define SFMVUNSET(f)	(!((f)->bits&SF_MVSIZE) ? 0 : \
519				(((f)->bits &= ~SF_MVSIZE), ((f)->size /= SF_NMAP)) )
520
521#define SFCLRBITS(f)	(SFMVUNSET(f), ((f)->bits &= ~SF_TMPBITS) )
522
523
524/* bits for the mode field, SF_INIT defined in sfio_t.h */
525#define SF_RC		00000010	/* peeking for a record			*/
526#define SF_RV		00000020	/* reserve without read	or most write	*/
527#define SF_LOCK		00000040	/* stream is locked for io op		*/
528#define SF_PUSH		00000100	/* stream has been pushed		*/
529#define SF_POOL		00000200	/* stream is in a pool but not current	*/
530#define SF_PEEK		00000400	/* there is a pending peek		*/
531#define SF_PKRD		00001000	/* did a peek read			*/
532#define SF_GETR		00002000	/* did a getr on this stream		*/
533#define SF_SYNCED	00004000	/* stream was synced			*/
534#define SF_STDIO	00010000	/* given up the buffer to stdio		*/
535#define SF_AVAIL	00020000	/* was closed, available for reuse	*/
536#define SF_LOCAL	00100000	/* sentinel for a local call		*/
537
538#ifdef DEBUG
539#define ASSERT(p)	((p) ? 0 : (abort(),0) )
540#else
541#define ASSERT(p)
542#endif
543
544/* short-hands */
545#define NIL(t)		((t)0)
546#define reg		register
547#ifndef uchar
548#define uchar		unsigned char
549#endif
550#ifndef ulong
551#define ulong		unsigned long
552#endif
553#ifndef uint
554#define uint		unsigned int
555#endif
556#ifndef ushort
557#define ushort		unsigned short
558#endif
559
560#define SECOND		1000	/* millisecond units */
561
562/* macros do determine stream types from sfstat_t data */
563#ifndef S_IFDIR
564#define S_IFDIR	0
565#endif
566#ifndef S_IFREG
567#define S_IFREG	0
568#endif
569#ifndef S_IFCHR
570#define S_IFCHR	0
571#endif
572#ifndef S_IFIFO
573#define S_IFIFO	0
574#endif
575#ifndef S_ISOCK
576#define S_ISOCK	0
577#endif
578
579#ifndef S_IFMT
580#define S_IFMT	(S_IFDIR|S_IFREG|S_IFCHR|S_IFIFO|S_ISOCK)
581#endif
582
583#ifndef S_ISDIR
584#define S_ISDIR(m)	(((m)&S_IFMT) == S_IFDIR)
585#endif
586#ifndef S_ISREG
587#define S_ISREG(m)	(((m)&S_IFMT) == S_IFREG)
588#endif
589#ifndef S_ISCHR
590#define S_ISCHR(m)	(((m)&S_IFMT) == S_IFCHR)
591#endif
592
593#ifndef S_ISFIFO
594#	if S_IFIFO
595#		define S_ISFIFO(m)	(((m)&S_IFMT) == S_IFIFO)
596#	else
597#		define S_ISFIFO(m)	(0)
598#	endif
599#endif
600
601#ifdef S_IRUSR
602#define SF_CREATMODE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
603#else
604#define SF_CREATMODE	0666
605#endif
606
607/* set close-on-exec */
608#ifdef F_SETFD
609#	ifndef FD_CLOEXEC
610#		define FD_CLOEXEC	1
611#	endif /*FD_CLOEXEC*/
612#	define SETCLOEXEC(fd)		((void)fcntl((fd),F_SETFD,FD_CLOEXEC))
613#else
614#	ifdef FIOCLEX
615#		define SETCLOEXEC(fd)	((void)ioctl((fd),FIOCLEX,0))
616#	else
617#		define SETCLOEXEC(fd)
618#	endif /*FIOCLEX*/
619#endif /*F_SETFD*/
620
621#define SF_FD_CLOEXEC			0x0001
622
623/* a couple of error number that we use, default values are like Linux */
624#ifndef EINTR
625#define EINTR	4
626#endif
627#ifndef EBADF
628#define EBADF	9
629#endif
630#ifndef EAGAIN
631#define EAGAIN	11
632#endif
633#ifndef ENOMEM
634#define ENOMEM	12
635#endif
636#ifndef EINVAL
637#define EINVAL	22
638#endif
639#ifndef ESPIPE
640#define ESPIPE	29
641#endif
642
643/* function to get the decimal point for local environment */
644#if !defined(SFSETLOCALE) && _PACKAGE_ast
645#include "lclib.h"
646#define SFSETLOCALE(dp,tp) \
647	do if (*(dp) == 0) { \
648		Lc_numeric_t*	lv = (Lc_numeric_t*)LCINFO(AST_LC_NUMERIC)->data; \
649		*(dp) = lv->decimal; \
650		*(tp) = lv->thousand; \
651	} while (0)
652#endif /*!defined(SFSETLOCALE) && _PACKAGE_ast*/
653
654#if !defined(SFSETLOCALE) && _lib_locale
655#include	<locale.h>
656#define SFSETLOCALE(decimal,thousand) \
657	do { struct lconv*	lv; \
658	  if(*(decimal) == 0) \
659	  { *(decimal) = '.'; \
660	    *(thousand) = -1; \
661	    if((lv = localeconv())) \
662	    { if(lv->decimal_point && *lv->decimal_point) \
663	    	*(decimal) = *(unsigned char*)lv->decimal_point; \
664	      if(lv->thousands_sep && *lv->thousands_sep) \
665	    	*(thousand) = *(unsigned char*)lv->thousands_sep; \
666	    } \
667	  } \
668	} while (0)
669#endif /*!defined(SFSETLOCALE) && _lib_locale*/
670
671#if !defined(SFSETLOCALE)
672#define SFSETLOCALE(decimal,thousand)	(*(decimal)='.',*(thousand)=-1)
673#endif
674
675/* stream pool structure. */
676typedef struct _sfpool_s	Sfpool_t;
677struct _sfpool_s
678{	Sfpool_t*	next;
679	int		mode;		/* type of pool			*/
680	int		s_sf;		/* size of pool array		*/
681	int		n_sf;		/* number currently in pool	*/
682	Sfio_t**	sf;		/* array of streams		*/
683	Sfio_t*		array[3];	/* start with 3			*/
684	Vtmutex_t	mutex;		/* mutex lock object		*/
685};
686
687/* reserve buffer structure */
688typedef struct _sfrsrv_s	Sfrsrv_t;
689struct _sfrsrv_s
690{	ssize_t		slen;		/* last string length		*/
691	ssize_t		size;		/* buffer size			*/
692	uchar		data[1];	/* data buffer			*/
693};
694
695/* co-process structure */
696typedef struct _sfproc_s	Sfproc_t;
697struct _sfproc_s
698{	int		pid;	/* process id			*/
699	uchar*		rdata;	/* read data being cached	*/
700	int		ndata;	/* size of cached data		*/
701	int		size;	/* buffer size			*/
702	int		file;	/* saved file descriptor	*/
703	int		sigp;	/* sigpipe protection needed	*/
704};
705
706/* extensions to sfvprintf/sfvscanf */
707#define FP_SET(fp,fn)	(fp < 0 ? (fn += 1) : (fn = fp) )
708#define FP_WIDTH	0
709#define FP_PRECIS	1
710#define FP_BASE		2
711#define FP_STR		3
712#define FP_SIZE		4
713#define FP_INDEX	5	/* index size	*/
714
715typedef struct _fmt_s		Fmt_t;
716typedef struct _fmtpos_s	Fmtpos_t;
717typedef union
718{	int		i, *ip;
719	long		l, *lp;
720	short		h, *hp;
721	uint		ui;
722	ulong		ul;
723	ushort		uh;
724	Sflong_t	ll, *llp;
725	Sfulong_t	lu;
726	Sfdouble_t	ld;
727	double		d;
728	float		f;
729#if _has_multibyte
730	wchar_t		wc;
731	wchar_t		*ws, **wsp;
732#endif
733	char		c, *s, **sp;
734	uchar		uc, *us, **usp;
735	Void_t		*vp;
736	Sffmt_t		*ft;
737} Argv_t;
738
739struct _fmt_s
740{	char*		form;		/* format string		*/
741	va_list		args;		/* corresponding arglist	*/
742	SFMBDCL(mbs)			/* multibyte parsing state	*/
743
744	char*		oform;		/* original format string	*/
745	va_list		oargs;		/* original arg list		*/
746	int		argn;		/* number of args already used	*/
747	Fmtpos_t*	fp;		/* position list		*/
748
749	Sffmt_t*	ft;		/* formatting environment	*/
750	Sffmtevent_f	eventf;		/* event function		*/
751	Fmt_t*		next;		/* stack frame pointer		*/
752};
753
754struct _fmtpos_s
755{	Sffmt_t	ft;			/* environment			*/
756	Argv_t	argv;			/* argument value		*/
757	int	fmt;			/* original format		*/
758	int	need[FP_INDEX];		/* positions depending on	*/
759};
760
761#define LEFTP		'('
762#define RIGHTP		')'
763#define QUOTE		'\''
764
765#ifndef CHAR_BIT
766#define CHAR_BIT	8
767#endif
768
769#define FMTSET(ft, frm,ags, fv, sz, flgs, wid,pr,bs, ts,ns) \
770	((ft->form = (char*)frm), va_copy(ft->args,ags), \
771	 (ft->fmt = fv), (ft->size = sz), \
772	 (ft->flags = (flgs&SFFMT_SET)), \
773	 (ft->width = wid), (ft->precis = pr), (ft->base = bs), \
774	 (ft->t_str = ts), (ft->n_str = ns) )
775#define FMTGET(ft, frm,ags, fv, sz, flgs, wid,pr,bs) \
776	((frm = ft->form), va_copy(ags,ft->args), \
777	 (fv = ft->fmt), (sz = ft->size), \
778	 (flgs = (flgs&~(SFFMT_SET))|(ft->flags&SFFMT_SET)), \
779	 (wid = ft->width), (pr = ft->precis), (bs = ft->base) )
780
781/* format flags&types, must coexist with those in sfio.h */
782#define SFFMT_FORBIDDEN 000077777777	/* for sfio.h only		*/
783#define SFFMT_EFORMAT	001000000000	/* sfcvt converting %e		*/
784#define SFFMT_MINUS	002000000000	/* minus sign			*/
785#define SFFMT_AFORMAT	004000000000	/* sfcvt converting %a		*/
786#define SFFMT_UPPER	010000000000	/* sfcvt converting upper	*/
787
788#define SFFMT_TYPES	(SFFMT_SHORT|SFFMT_SSHORT | SFFMT_LONG|SFFMT_LLONG|\
789			 SFFMT_LDOUBLE | SFFMT_IFLAG|SFFMT_JFLAG| \
790			 SFFMT_TFLAG | SFFMT_ZFLAG )
791
792/* type of elements to be converted */
793#define SFFMT_INT	001		/* %d,%i 		*/
794#define SFFMT_UINT	002		/* %u,o,x etc.		*/
795#define SFFMT_FLOAT	004		/* %f,e,g etc.		*/
796#define SFFMT_CHAR	010		/* %c,C			*/
797#define SFFMT_POINTER	020		/* %p,n,s,S		*/
798#define SFFMT_CLASS	040		/* %[			*/
799
800/* local variables used across sf-functions */
801typedef void  (*Sfnotify_f)_ARG_((Sfio_t*, int, void*));
802#define _Sfpage		(_Sfextern.sf_page)
803#define _Sfpool		(_Sfextern.sf_pool)
804#define _Sfpmove	(_Sfextern.sf_pmove)
805#define _Sfstack	(_Sfextern.sf_stack)
806#define _Sfnotify	(_Sfextern.sf_notify)
807#define _Sfstdsync	(_Sfextern.sf_stdsync)
808#define _Sfudisc	(&(_Sfextern.sf_udisc))
809#define _Sfcleanup	(_Sfextern.sf_cleanup)
810#define _Sfexiting	(_Sfextern.sf_exiting)
811#define _Sfdone		(_Sfextern.sf_done)
812#define _Sfonce		(_Sfextern.sf_once)
813#define _Sfoncef	(_Sfextern.sf_oncef)
814#define _Sfmutex	(_Sfextern.sf_mutex)
815typedef struct _sfextern_s
816{	ssize_t			sf_page;
817	struct _sfpool_s	sf_pool;
818	int			(*sf_pmove)_ARG_((Sfio_t*, int));
819	Sfio_t*			(*sf_stack)_ARG_((Sfio_t*, Sfio_t*));
820	void			(*sf_notify)_ARG_((Sfio_t*, int, void*));
821	int			(*sf_stdsync)_ARG_((Sfio_t*));
822	struct _sfdisc_s	sf_udisc;
823	void			(*sf_cleanup)_ARG_((void));
824	int			sf_exiting;
825	int			sf_done;
826	Vtonce_t*		sf_once;
827	void			(*sf_oncef)_ARG_((void));
828	Vtmutex_t*		sf_mutex;
829} Sfextern_t;
830
831/* get the real value of a byte in a coded long or ulong */
832#define SFUVALUE(v)	(((ulong)(v))&(SF_MORE-1))
833#define SFSVALUE(v)	((( long)(v))&(SF_SIGN-1))
834#define SFBVALUE(v)	(((ulong)(v))&(SF_BYTE-1))
835
836/* pick this many bits in each iteration of double encoding */
837#define SF_PRECIS	7
838
839/* grain size for buffer increment */
840#define SF_GRAIN	1024
841#define SF_PAGE		((ssize_t)(SF_GRAIN*sizeof(int)*2))
842
843/* when the buffer is empty, certain io requests may be better done directly
844   on the given application buffers. The below condition determines when.
845*/
846#define SFDIRECT(f,n)	(((ssize_t)(n) >= (f)->size) || \
847			 ((n) >= SF_GRAIN && (ssize_t)(n) >= (f)->size/16 ) )
848
849/* number of pages to memory map at a time */
850#if _ptr_bits >= 64
851#define SF_NMAP		1024
852#else
853#define SF_NMAP		32
854#endif
855
856#ifndef MAP_VARIABLE
857#define MAP_VARIABLE	0
858#endif
859#ifndef _mmap_fixed
860#define _mmap_fixed	0
861#endif
862
863/* set/unset sequential states for mmap */
864#if _lib_madvise && defined(MADV_SEQUENTIAL) && defined(MADV_NORMAL)
865#define SFMMSEQON(f,a,s) \
866		do { int oerrno = errno; \
867		     (void)madvise((caddr_t)(a),(size_t)(s),MADV_SEQUENTIAL); \
868		     errno = oerrno; \
869		} while(0)
870#define SFMMSEQOFF(f,a,s) \
871		do { int oerrno = errno; \
872		     (void)madvise((caddr_t)(a),(size_t)(s),MADV_NORMAL); \
873		     errno = oerrno; \
874		} while(0)
875#else
876#define SFMMSEQON(f,a,s)
877#define SFMMSEQOFF(f,a,s)
878#endif
879
880#define SFMUNMAP(f,a,s)		(sysmunmapf((caddr_t)(a),(size_t)(s)), \
881				 ((f)->endb = (f)->endr = (f)->endw = (f)->next = \
882				  (f)->data = NIL(uchar*)) )
883
884/* safe closing function */
885#define CLOSE(f)	{ while(sysclosef(f) < 0 && errno == EINTR) errno = 0; }
886
887/* the bottomless bit bucket */
888#define DEVNULL		"/dev/null"
889#define SFSETNULL(f)	((f)->extent = (Sfoff_t)(-1), (f)->bits |= SF_NULL)
890#define SFISNULL(f)	((f)->extent < 0 && ((f)->bits&SF_NULL) )
891
892#define SFKILL(f)	((f)->mode = (SF_AVAIL|SF_LOCK) )
893#define SFKILLED(f)	(((f)->mode&(SF_AVAIL|SF_LOCK)) == (SF_AVAIL|SF_LOCK) )
894
895/* exception types */
896#define SF_EDONE	0	/* stop this operation and return	*/
897#define SF_EDISC	1	/* discipline says it's ok		*/
898#define SF_ESTACK	2	/* stack was popped			*/
899#define SF_ECONT	3	/* can continue normally		*/
900
901#define SETLOCAL(f)	((f)->mode |= SF_LOCAL)
902#define GETLOCAL(f,v)	((v) = ((f)->mode&SF_LOCAL), (f)->mode &= ~SF_LOCAL, (v))
903#define SFWRALL(f)	((f)->mode |= SF_RV)
904#define SFISALL(f,v)	((((v) = (f)->mode&SF_RV) ? ((f)->mode &= ~SF_RV) : 0), \
905			 ((v) || ((f)->flags&(SF_SHARE|SF_APPENDWR|SF_WHOLE)) ) )
906#define SFSK(f,a,o,d)	(SETLOCAL(f),sfsk(f,(Sfoff_t)a,o,d))
907#define SFRD(f,b,n,d)	(SETLOCAL(f),sfrd(f,(Void_t*)b,n,d))
908#define SFWR(f,b,n,d)	(SETLOCAL(f),sfwr(f,(Void_t*)b,n,d))
909#define SFSYNC(f)	(SETLOCAL(f),sfsync(f))
910#define SFCLOSE(f)	(SETLOCAL(f),sfclose(f))
911#define SFFLSBUF(f,n)	(SETLOCAL(f),_sfflsbuf(f,n))
912#define SFFILBUF(f,n)	(SETLOCAL(f),_sffilbuf(f,n))
913#define SFSETBUF(f,s,n)	(SETLOCAL(f),sfsetbuf(f,s,n))
914#define SFWRITE(f,s,n)	(SETLOCAL(f),sfwrite(f,s,n))
915#define SFREAD(f,s,n)	(SETLOCAL(f),sfread(f,s,n))
916#define SFSEEK(f,p,t)	(SETLOCAL(f),sfseek(f,p,t))
917#define SFNPUTC(f,c,n)	(SETLOCAL(f),sfnputc(f,c,n))
918#define SFRAISE(f,e,d)	(SETLOCAL(f),sfraise(f,e,d))
919
920/* lock/open a stream */
921#define SFMODE(f,l)	((f)->mode & ~(SF_RV|SF_RC|((l) ? SF_LOCK : 0)) )
922#define SFLOCK(f,l)	(void)((f)->mode |= SF_LOCK, (f)->endr = (f)->endw = (f)->data)
923#define _SFOPENRD(f)	((f)->endr = ((f)->flags&SF_MTSAFE) ? (f)->data : (f)->endb)
924#define _SFOPENWR(f)	((f)->endw = ((f)->flags&(SF_MTSAFE|SF_LINE)) ? (f)->data : (f)->endb)
925#define _SFOPEN(f)	((f)->mode == SF_READ  ? _SFOPENRD(f) : \
926			 (f)->mode == SF_WRITE ? _SFOPENWR(f) : \
927			 ((f)->endw = (f)->endr = (f)->data) )
928#define SFOPEN(f,l)	(void)((l) ? 0 : \
929				((f)->mode &= ~(SF_LOCK|SF_RC|SF_RV), _SFOPEN(f), 0) )
930
931/* check to see if the stream can be accessed */
932#define SFFROZEN(f)	(((f)->mode&(SF_PUSH|SF_LOCK|SF_PEEK)) ? 1 : \
933			 !((f)->mode&SF_STDIO) ? 0 : \
934			 _Sfstdsync ? (*_Sfstdsync)(f) : (((f)->mode &= ~SF_STDIO),0) )
935
936
937/* set discipline code */
938#define SFDISC(f,dc,iof) \
939	{	Sfdisc_t* d; \
940		if(!(dc)) \
941			d = (dc) = (f)->disc; \
942		else 	d = (f->bits&SF_DCDOWN) ? ((dc) = (dc)->disc) : (dc); \
943		while(d && !(d->iof))	d = d->disc; \
944		if(d)	(dc) = d; \
945	}
946#define SFDCRD(f,buf,n,dc,rv) \
947	{	int		dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
948		rv = (*dc->readf)(f,buf,n,dc); \
949		if(!dcdown)	f->bits &= ~SF_DCDOWN; \
950	}
951#define SFDCWR(f,buf,n,dc,rv) \
952	{	int		dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
953		rv = (*dc->writef)(f,buf,n,dc); \
954		if(!dcdown)	f->bits &= ~SF_DCDOWN; \
955	}
956#define SFDCSK(f,addr,type,dc,rv) \
957	{	int		dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
958		rv = (*dc->seekf)(f,addr,type,dc); \
959		if(!dcdown)	f->bits &= ~SF_DCDOWN; \
960	}
961
962/* fast peek of a stream */
963#define _SFAVAIL(f,s,n)	((n) = (f)->endb - ((s) = (f)->next) )
964#define SFRPEEK(f,s,n)	(_SFAVAIL(f,s,n) > 0 ? (n) : \
965				((n) = SFFILBUF(f,-1), (s) = (f)->next, (n)) )
966#define SFWPEEK(f,s,n)	(_SFAVAIL(f,s,n) > 0 ? (n) : \
967				((n) = SFFLSBUF(f,-1), (s) = (f)->next, (n)) )
968
969/* more than this for a line buffer, we might as well flush */
970#define HIFORLINE	128
971
972/* string stream extent */
973#define SFSTRSIZE(f)	{ Sfoff_t s = (f)->next - (f)->data; \
974			  if(s > (f)->here) \
975			    { (f)->here = s; if(s > (f)->extent) (f)->extent = s; } \
976			}
977
978/* control flags for open() */
979#ifdef O_CREAT
980#define _has_oflags	1
981#else	/* for example, research UNIX */
982#define _has_oflags	0
983#define O_CREAT		004
984#define O_TRUNC		010
985#define O_APPEND	020
986#define O_EXCL		040
987
988#ifndef O_RDONLY
989#define	O_RDONLY	000
990#endif
991#ifndef O_WRONLY
992#define O_WRONLY	001
993#endif
994#ifndef O_RDWR
995#define O_RDWR		002
996#endif
997#endif /*O_CREAT*/
998
999#ifndef O_BINARY
1000#define O_BINARY	000
1001#endif
1002#ifndef O_TEXT
1003#define O_TEXT		000
1004#endif
1005#ifndef O_TEMPORARY
1006#define O_TEMPORARY	000
1007#endif
1008
1009#define	SF_RADIX	64	/* maximum integer conversion base */
1010
1011#if _PACKAGE_ast
1012#define SF_MAXINT	INT_MAX
1013#define SF_MAXLONG	LONG_MAX
1014#else
1015#define SF_MAXINT	((int)(((uint)~0) >> 1))
1016#define SF_MAXLONG	((long)(((ulong)~0L) >> 1))
1017#endif
1018
1019#define SF_MAXCHAR	((uchar)(~0))
1020
1021/* floating point to ascii conversion */
1022#define SF_MAXEXP10	6
1023#define SF_MAXPOW10	(1 << SF_MAXEXP10)
1024#if !_ast_fltmax_double
1025#define SF_FDIGITS	1024		/* max allowed fractional digits */
1026#define SF_IDIGITS	(8*1024)	/* max number of digits in int part */
1027#else
1028#define SF_FDIGITS	256		/* max allowed fractional digits */
1029#define SF_IDIGITS	1024		/* max number of digits in int part */
1030#endif
1031#define SF_MAXDIGITS	(((SF_FDIGITS+SF_IDIGITS)/sizeof(int) + 1)*sizeof(int))
1032
1033/* tables for numerical translation */
1034#define _Sfpos10	(_Sftable.sf_pos10)
1035#define _Sfneg10	(_Sftable.sf_neg10)
1036#define _Sfdec		(_Sftable.sf_dec)
1037#define _Sfdigits	(_Sftable.sf_digits)
1038#define _Sfcvinitf	(_Sftable.sf_cvinitf)
1039#define _Sfcvinit	(_Sftable.sf_cvinit)
1040#define _Sffmtposf	(_Sftable.sf_fmtposf)
1041#define _Sffmtintf	(_Sftable.sf_fmtintf)
1042#define _Sfcv36		(_Sftable.sf_cv36)
1043#define _Sfcv64		(_Sftable.sf_cv64)
1044#define _Sftype		(_Sftable.sf_type)
1045#define _Sfieee		(&_Sftable.sf_ieee)
1046#define _Sffinf		(_Sftable.sf_ieee.fltinf)
1047#define _Sfdinf		(_Sftable.sf_ieee.dblinf)
1048#define _Sflinf		(_Sftable.sf_ieee.ldblinf)
1049#define _Sffnan		(_Sftable.sf_ieee.fltnan)
1050#define _Sfdnan		(_Sftable.sf_ieee.dblnan)
1051#define _Sflnan		(_Sftable.sf_ieee.ldblnan)
1052#define _Sffpow10	(_Sftable.sf_flt_pow10)
1053#define _Sfdpow10	(_Sftable.sf_dbl_pow10)
1054#define _Sflpow10	(_Sftable.sf_ldbl_pow10)
1055typedef struct _sfieee_s	Sfieee_t;
1056struct _sfieee_s
1057{	float		fltnan;		/* float NAN			*/
1058	float		fltinf;		/* float INF			*/
1059	double		dblnan;		/* double NAN			*/
1060	double		dblinf;		/* double INF			*/
1061	Sfdouble_t	ldblnan;	/* Sfdouble_t NAN		*/
1062	Sfdouble_t	ldblinf;	/* Sfdouble_t INF		*/
1063};
1064typedef struct _sftab_
1065{	Sfdouble_t	sf_pos10[SF_MAXEXP10];	/* positive powers of 10	*/
1066	Sfdouble_t	sf_neg10[SF_MAXEXP10];	/* negative powers of 10	*/
1067	uchar		sf_dec[200];		/* ascii reps of values < 100	*/
1068	char*		sf_digits;		/* digits for general bases	*/
1069	int		(*sf_cvinitf)();	/* initialization function	*/
1070	int		sf_cvinit;		/* initialization state		*/
1071	Fmtpos_t*	(*sf_fmtposf)_ARG_((Sfio_t*,const char*,va_list,Sffmt_t*,int));
1072	char*		(*sf_fmtintf)_ARG_((const char*,int*));
1073	float*		sf_flt_pow10;		/* float powers of 10		*/
1074	double*		sf_dbl_pow10;		/* double powers of 10		*/
1075	Sfdouble_t*	sf_ldbl_pow10;		/* Sfdouble_t powers of 10	*/
1076	uchar		sf_cv36[SF_MAXCHAR+1];	/* conversion for base [2-36]	*/
1077	uchar		sf_cv64[SF_MAXCHAR+1];	/* conversion for base [37-64]	*/
1078	uchar		sf_type[SF_MAXCHAR+1];	/* conversion formats&types	*/
1079	Sfieee_t	sf_ieee;		/* IEEE floating point constants*/
1080} Sftab_t;
1081
1082/* thread-safe macro/function to initialize _Sfcv* conversion tables */
1083#define SFCVINIT()      (_Sfcvinit ? 1 : (_Sfcvinit = (*_Sfcvinitf)()) )
1084
1085/* sfucvt() converts decimal integers to ASCII */
1086#define SFDIGIT(v,scale,digit) \
1087	{ if(v < 5*scale) \
1088		if(v < 2*scale) \
1089			if(v < 1*scale) \
1090				{ digit = '0'; } \
1091			else	{ digit = '1'; v -= 1*scale; } \
1092		else	if(v < 3*scale) \
1093				{ digit = '2'; v -= 2*scale; } \
1094			else if(v < 4*scale) \
1095				{ digit = '3'; v -= 3*scale; } \
1096			else	{ digit = '4'; v -= 4*scale; } \
1097	  else	if(v < 7*scale) \
1098			if(v < 6*scale) \
1099				{ digit = '5'; v -= 5*scale; } \
1100			else	{ digit = '6'; v -= 6*scale; } \
1101		else	if(v < 8*scale) \
1102				{ digit = '7'; v -= 7*scale; } \
1103			else if(v < 9*scale) \
1104				{ digit = '8'; v -= 8*scale; } \
1105			else	{ digit = '9'; v -= 9*scale; } \
1106	}
1107#define sfucvt(v,s,n,list,type,utype) \
1108	{ while((utype)v >= 10000) \
1109	  {	n = v; v = (type)(((utype)v)/10000); \
1110		n = (type)((utype)n - ((utype)v)*10000); \
1111	  	s -= 4; SFDIGIT(n,1000,s[0]); SFDIGIT(n,100,s[1]); \
1112			s[2] = *(list = (char*)_Sfdec + (n <<= 1)); s[3] = *(list+1); \
1113	  } \
1114	  if(v < 100) \
1115	  { if(v < 10) \
1116	    { 	s -= 1; s[0] = (char)('0'+v); \
1117	    } else \
1118	    { 	s -= 2; s[0] = *(list = (char*)_Sfdec + (v <<= 1)); s[1] = *(list+1); \
1119	    } \
1120	  } else \
1121	  { if(v < 1000) \
1122	    { 	s -= 3; SFDIGIT(v,100,s[0]); \
1123			s[1] = *(list = (char*)_Sfdec + (v <<= 1)); s[2] = *(list+1); \
1124	    } else \
1125	    {	s -= 4; SFDIGIT(v,1000,s[0]); SFDIGIT(v,100,s[1]); \
1126			s[2] = *(list = (char*)_Sfdec + (v <<= 1)); s[3] = *(list+1); \
1127	    } \
1128	  } \
1129	}
1130
1131/* handy functions */
1132#undef min
1133#undef max
1134#define min(x,y)	((x) < (y) ? (x) : (y))
1135#define max(x,y)	((x) > (y) ? (x) : (y))
1136
1137/* fast functions for memory copy and memory clear */
1138#if _PACKAGE_ast
1139#define memclear(s,n)	memzero(s,n)
1140#else
1141#if _lib_bcopy && !_lib_memcpy
1142#define memcpy(to,fr,n)	bcopy((fr),(to),(n))
1143#endif
1144#if _lib_bzero && !_lib_memset
1145#define memclear(s,n)	bzero((s),(n))
1146#else
1147#define memclear(s,n)	memset((s),'\0',(n))
1148#endif
1149#endif /*_PACKAGE_ast*/
1150
1151/* note that MEMCPY advances the associated pointers */
1152#define MEMCPY(to,fr,n) \
1153	switch(n) \
1154	{ default : memcpy((Void_t*)to,(Void_t*)fr,n); to += n; fr += n; break; \
1155	  case  7 : *to++ = *fr++; \
1156	  case  6 : *to++ = *fr++; \
1157	  case  5 : *to++ = *fr++; \
1158	  case  4 : *to++ = *fr++; \
1159	  case  3 : *to++ = *fr++; \
1160	  case  2 : *to++ = *fr++; \
1161	  case  1 : *to++ = *fr++; \
1162	}
1163#define MEMSET(s,c,n) \
1164	switch(n) \
1165	{ default : memset((Void_t*)s,(int)c,n); s += n; break; \
1166	  case  7 : *s++ = c; \
1167	  case  6 : *s++ = c; \
1168	  case  5 : *s++ = c; \
1169	  case  4 : *s++ = c; \
1170	  case  3 : *s++ = c; \
1171	  case  2 : *s++ = c; \
1172	  case  1 : *s++ = c; \
1173	}
1174
1175_BEGIN_EXTERNS_
1176
1177extern Sftab_t		_Sftable;
1178
1179extern int		_sfpopen _ARG_((Sfio_t*, int, int, int));
1180extern int		_sfpclose _ARG_((Sfio_t*));
1181extern int		_sfexcept _ARG_((Sfio_t*, int, ssize_t, Sfdisc_t*));
1182extern Sfrsrv_t*	_sfrsrv _ARG_((Sfio_t*, ssize_t));
1183extern int		_sfsetpool _ARG_((Sfio_t*));
1184extern char*		_sfcvt _ARG_((Void_t*,char*,size_t,int,int*,int*,int*,int));
1185extern char**		_sfgetpath _ARG_((char*));
1186
1187#if _BLD_sfio && defined(__EXPORT__)
1188#define extern		__EXPORT__
1189#endif
1190#if !_BLD_sfio && defined(__IMPORT__)
1191#define extern		extern __IMPORT__
1192#endif
1193
1194extern Sfextern_t	_Sfextern;
1195
1196extern int		_sfmode _ARG_((Sfio_t*, int, int));
1197extern int		_sftype _ARG_((const char*, int*, int*, int*));
1198
1199#undef	extern
1200
1201#ifndef errno
1202extern int		errno;
1203#endif
1204
1205/* for portable encoding of double values */
1206#ifndef frexpl
1207#if _ast_fltmax_double
1208#define frexpl		frexp
1209#endif
1210#if !_lib_frexpl
1211extern Sfdouble_t	frexpl _ARG_((Sfdouble_t, int*));
1212#endif
1213#endif
1214#ifndef ldexpl
1215#if _ast_fltmax_double
1216#define ldexpl		ldexp
1217#endif
1218#if !_lib_ldexpl
1219extern Sfdouble_t	ldexpl _ARG_((Sfdouble_t, int));
1220#endif
1221#endif
1222
1223#if !_PACKAGE_ast
1224
1225#if !__STDC__ && !_hdr_stdlib
1226extern void	abort _ARG_((void));
1227extern int	atexit _ARG_((void(*)(void)));
1228extern char*	getenv _ARG_((const char*));
1229extern void*	malloc _ARG_((size_t));
1230extern void*	realloc _ARG_((void*, size_t));
1231extern void	free _ARG_((void*));
1232extern size_t	strlen _ARG_((const char*));
1233extern char*	strcpy _ARG_((char*, const char*));
1234
1235extern Void_t*	memset _ARG_((void*, int, size_t));
1236extern Void_t*	memchr _ARG_((const void*, int, size_t));
1237extern Void_t*	memccpy _ARG_((void*, const void*, int, size_t));
1238#ifndef memcpy
1239extern Void_t*	memcpy _ARG_((void*, const void*, size_t));
1240#endif
1241#if !defined(strtod)
1242extern double	strtod _ARG_((const char*, char**));
1243#endif
1244#if !defined(remove)
1245extern int	sysremovef _ARG_((const char*));
1246#endif
1247#endif /* !__STDC__ && !_hdr_stdlib */
1248
1249#if !_hdr_unistd
1250#if _proto_open && __cplusplus
1251extern int	sysopenf _ARG_((const char*, int, ...));
1252#endif
1253extern int	sysclosef _ARG_((int));
1254extern ssize_t	sysreadf _ARG_((int, void*, size_t));
1255extern ssize_t	syswritef _ARG_((int, const void*, size_t));
1256extern sfoff_t	syslseekf _ARG_((int, sfoff_t, int));
1257extern int	sysdupf _ARG_((int));
1258extern int	syspipef _ARG_((int*));
1259extern int	sysaccessf _ARG_((const char*, int));
1260extern int	sysremovef _ARG_((const char*));
1261extern int	sysfstatf _ARG_((int, sfstat_t*));
1262extern int	sysstatf _ARG_((const char*, sfstat_t*));
1263
1264extern int	isatty _ARG_((int));
1265
1266extern int	wait _ARG_((int*));
1267extern uint	sleep _ARG_((uint));
1268extern int	execl _ARG_((const char*, const char*,...));
1269extern int	execv _ARG_((const char*, char**));
1270#if !defined(fork)
1271extern int	fork _ARG_((void));
1272#endif
1273#if _lib_unlink
1274extern int	unlink _ARG_((const char*));
1275#endif
1276
1277#endif /*_hdr_unistd*/
1278
1279#if _lib_bcopy && !_proto_bcopy
1280extern void	bcopy _ARG_((const void*, void*, size_t));
1281#endif
1282#if _lib_bzero && !_proto_bzero
1283extern void	bzero _ARG_((void*, size_t));
1284#endif
1285
1286extern time_t	time _ARG_((time_t*));
1287extern int	waitpid _ARG_((int,int*,int));
1288extern void	_exit _ARG_((int));
1289typedef int(*	Onexit_f)_ARG_((void));
1290extern Onexit_f	onexit _ARG_((Onexit_f));
1291
1292#if _lib_vfork && !_hdr_vfork && !_sys_vfork
1293extern pid_t	vfork _ARG_((void));
1294#endif /*_lib_vfork*/
1295
1296#if _lib_poll
1297#if _lib_poll_fd_1
1298extern int	poll _ARG_((struct pollfd*, ulong, int));
1299#else
1300extern int	poll _ARG_((ulong, struct pollfd*, int));
1301#endif
1302#endif /*_lib_poll*/
1303
1304#endif /* _PACKAGE_ast */
1305
1306_END_EXTERNS_
1307
1308#endif /*_SFHDR_H*/
1309