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