1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 #if !defined(_BLD_sfio) && !defined(_BLD_stdio)
28 /* Internal definitions for sfio.
29 ** Written by Kiem-Phong Vo
43 #include "FEATURE/sfio"
44 #include "FEATURE/mmap"
46 /* define va_list, etc. before including sfio_t.h (sfio.h) */
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
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
70 #include "FEATURE/common"
74 #endif /* !_PACKAGE_ast */
78 /* note that the macro vt_threaded has effect on vthread.h */
81 /* file system info */
89 /* ast always provides multibyte handling */
94 #define _lib_mbrtowc 1
95 #define _lib_wcrtomb 1
97 #if _mem_st_blksize_stat
98 #define _stat_blksize 1
101 #if _lib_localeconv && _hdr_locale
102 #define _lib_locale 1
105 #define sfoff_t off_t
106 #define sfstat_t struct stat
107 #define sysclosef close
108 #define syscreatf creat
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
123 #else /*!_PACKAGE_ast*/
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.
160 #include <sys/time.h>
164 #include <sys/stat.h>
186 #include <sys/filio.h>
187 #endif /*_sys_filio*/
188 #endif /*_hdr_filio*/
196 #if !_LARGEFILE64_SOURCE /* turn off the *64 stuff */
198 #undef _typ_struct_stat64
204 #undef _lib_ftruncate64
208 #endif /*!_LARGEFILE64_SOURCE */
210 /* see if we can use memory mapping for io */
211 #if _LARGEFILE64_SOURCE && !_lib_mmap64
222 #include <sys/mman.h>
225 /* standardize system calls and types dealing with files */
227 #define sfoff_t off64_t
229 #define sfoff_t off_t
231 #if _typ_struct_stat64
232 #define sfstat_t struct stat64
234 #define sfstat_t struct stat
237 #define syslseekf lseek64
239 #define syslseekf lseek
242 #define sysstatf stat64
244 #define sysstatf stat
247 #define sysfstatf fstat64
249 #define sysfstatf fstat
252 #define sysmmapf mmap64
254 #define sysmmapf mmap
257 #define sysmunmapf munmap64
259 #define sysmunmapf munmap
262 #define sysopenf open64
264 #define sysopenf open
267 #define syscreatf creat64
269 #define syscreatf creat
272 #define sysclosef close64
274 #define sysclosef close
277 #undef _lib_ftruncate
278 #define _lib_ftruncate 1
279 #define sysftruncatef ftruncate64
281 #if !_lib_ftruncate64 && _lib_ftruncate
282 #define sysftruncatef ftruncate
285 #define sysremovef remove
287 #define sysremovef unlink
290 #define sysreadf read
291 #define syswritef write
292 #define syspipef pipe
294 #define sysfcntlf fcntl
296 #endif /*_PACKAGE_ast*/
302 #include "FEATURE/float"
307 /* deal with multi-byte character and string conversions */
312 #define _has_multibyte 1
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;
323 #if _hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc
324 #define _has_multibyte 1 /* Xopen-compliant */
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*/
333 #if !_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb
334 #define _has_multibyte 2 /* no shift states */
337 #define mbrtowc(wp,s,n,mb) mbtowc(wp, s, n)
339 #define wcrtomb(s,wc,mb) wctomb(s, wc)
340 #define SFMBCPY(to,fr)
342 #define SFMBSET(lhs,v)
344 #define SFMBLEN(s,mb) mbrtowc(NIL(wchar_t*), (s), SFMBMAX, (mb) )
345 #endif /*!_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb*/
348 #define SFMBMAX MB_CUR_MAX
350 #define SFMBMAX sizeof(Sflong_t)
353 #endif /* _PACKAGE_ast */
356 #define _has_multibyte 0 /* no multibyte support */
357 #define SFMBCPY(to,fr)
359 #define SFMBSET(lhs,v)
360 #define SFMBLEN(s,mb) (*(s) ? 1 : 0)
362 #endif /* _has_multibyte */
364 /* dealing with streams that might be accessed concurrently */
367 #define SFMTXdecl(ff,_mf_) Sfio_t* _mf_ = (ff)
368 #define SFMTXbegin(ff,_mf_,rv) \
369 { if((ff)->_flags&SF_MTSAFE) \
371 if(sfmutex((ff), SFMTX_LOCK) != 0) return(rv); \
373 { (*_Sfnotify)((_mf_), SF_MTACCESS, (Void_t*)(&(ff)) ); \
374 if(!(ff)) (ff) = (_mf_); \
378 #define SFMTXend(ff,_mf_) \
379 { if((ff)->_flags&SF_MTSAFE) \
381 (*_Sfnotify)((_mf_), SF_MTACCESS, NIL(Void_t*) ); \
382 sfmutex((ff), SFMTX_UNLOCK); \
387 #define SFONCE() (_Sfdone ? 0 : vtonce(_Sfonce,_Sfoncef))
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)
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); }
398 #define SFMTXDECL2(ff) SFMTXdecl((ff), _mtxf2_)
399 #define SFMTXBEGIN2(ff,v) { SFMTXbegin((ff), _mtxf2_, (v) ); }
400 #define SFMTXEND2(ff) { SFMTXend((ff), _mtxf2_); }
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); }
407 #else /*!vt_threaded*/
409 #undef SF_MTSAFE /* no need to worry about thread-safety */
412 #define SFONCE() /*(0)*/
414 #define SFMTXLOCK(f) /*(0)*/
415 #define SFMTXUNLOCK(f) /*(0)*/
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); }
423 #define SFMTXDECL2(ff) /*(0)*/
424 #define SFMTXBEGIN2(ff,v) /*(0)*/
425 #define SFMTXEND2(ff) /*(0)*/
427 #define POOLMTXLOCK(p)
428 #define POOLMTXUNLOCK(p)
429 #define POOLMTXENTER(p)
430 #define POOLMTXRETURN(p,v) { return(v); }
432 #endif /*vt_threaded*/
435 /* functions for polling readiness of streams */
439 #if _lib_poll_fd_1 || _lib_poll_fd_2
442 #endif /*_lib_select_*/
448 #define SFPOLL(pfd,n,tm) poll((pfd),(ulong)(n),(tm))
450 #define SFPOLL(pfd,n,tm) poll((ulong)(n),(pfd),(tm))
459 #include <sys/socket.h>
462 /* to test for executable access mode of a file */
467 /* alternative process forking */
468 #if _lib_vfork && !defined(fork) && !defined(sparc) && !defined(__sparc)
473 #include <sys/vfork.h>
478 /* to get rid of pesky compiler warnings */
480 #define NOTUSED(x) (void)(x)
482 #define NOTUSED(x) (&x,1)
485 /* Private flags in the "bits" field */
486 #define SF_MMAP 00000001 /* in memory mapping mode */
487 #define SF_BOTH 00000002 /* both read/write */
488 #define SF_HOLE 00000004 /* a hole of zero's was created */
489 #define SF_NULL 00000010 /* stream is /dev/null */
490 #define SF_SEQUENTIAL 00000020 /* sequential access */
491 #define SF_JUSTSEEK 00000040 /* just did a sfseek */
492 #define SF_PRIVATE 00000100 /* private stream to Sfio, no mutex */
493 #define SF_ENDING 00000200 /* no re-io on interrupts at closing */
494 #define SF_WIDE 00000400 /* in wide mode - stdio only */
496 /* "bits" flags that must be cleared in sfclrlock */
497 #define SF_TMPBITS 00170000
498 #define SF_DCDOWN 00010000 /* recurse down the discipline stack */
500 #define SF_WCFORMAT 00020000 /* wchar_t formatting - stdio only */
502 #define SFWCSET(f) ((f)->bits |= SF_WCFORMAT)
503 #define SFWCGET(f,v) (((v) = (f)->bits & SF_WCFORMAT), ((f)->bits &= ~SF_WCFORMAT) )
509 #define SF_MVSIZE 00040000 /* f->size was reset in sfmove() */
510 #define SFMVSET(f) (((f)->size *= SF_NMAP), ((f)->bits |= SF_MVSIZE) )
511 #define SFMVUNSET(f) (!((f)->bits&SF_MVSIZE) ? 0 : \
512 (((f)->bits &= ~SF_MVSIZE), ((f)->size /= SF_NMAP)) )
514 #define SFCLRBITS(f) (SFMVUNSET(f), ((f)->bits &= ~SF_TMPBITS) )
517 /* bits for the mode field, SF_INIT defined in sfio_t.h */
518 #define SF_RC 00000010 /* peeking for a record */
519 #define SF_RV 00000020 /* reserve without read or most write */
520 #define SF_LOCK 00000040 /* stream is locked for io op */
521 #define SF_PUSH 00000100 /* stream has been pushed */
522 #define SF_POOL 00000200 /* stream is in a pool but not current */
523 #define SF_PEEK 00000400 /* there is a pending peek */
524 #define SF_PKRD 00001000 /* did a peek read */
525 #define SF_GETR 00002000 /* did a getr on this stream */
526 #define SF_SYNCED 00004000 /* stream was synced */
527 #define SF_STDIO 00010000 /* given up the buffer to stdio */
528 #define SF_AVAIL 00020000 /* was closed, available for reuse */
529 #define SF_LOCAL 00100000 /* sentinel for a local call */
532 #define ASSERT(p) ((p) ? 0 : (abort(),0) )
538 #define NIL(t) ((t)0)
541 #define uchar unsigned char
544 #define ulong unsigned long
547 #define uint unsigned int
550 #define ushort unsigned short
553 #define SECOND 1000 /* millisecond units */
555 /* macros do determine stream types from sfstat_t data */
573 #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
576 #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
579 #define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
584 # define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO)
586 # define S_ISFIFO(m) (0)
591 #define SF_CREATMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
593 #define SF_CREATMODE 0666
596 /* set close-on-exec */
599 # define FD_CLOEXEC 1
600 # endif /*FD_CLOEXEC*/
601 # define SETCLOEXEC(fd) ((void)fcntl((fd),F_SETFD,FD_CLOEXEC))
604 # define SETCLOEXEC(fd) ((void)ioctl((fd),FIOCLEX,0))
606 # define SETCLOEXEC(fd)
610 /* a couple of error number that we use, default values are like Linux */
630 /* function to get the decimal point for local environment */
631 #if !defined(SFSETLOCALE) && _PACKAGE_ast
633 #define SFSETLOCALE(dp,tp) \
634 do if (*(dp) == 0) { \
635 Lc_numeric_t* lv = (Lc_numeric_t*)LCINFO(AST_LC_NUMERIC)->data; \
636 *(dp) = lv->decimal; \
637 if (tp) *(tp) = lv->thousand; \
639 #endif /*!defined(SFSETLOCALE) && _PACKAGE_ast*/
641 #if !defined(SFSETLOCALE) && _lib_locale
643 #define SFSETLOCALE(decimal,thousand) \
644 do { struct lconv* lv; \
645 if(*(decimal) == 0) \
646 { *(decimal) = '.'; \
647 if (thousand) *(thousand) = -1; \
648 if((lv = localeconv())) \
649 { if(lv->decimal_point && *lv->decimal_point) \
650 *(decimal) = *(unsigned char*)lv->decimal_point; \
651 if(thousand && lv->thousands_sep && *lv->thousands_sep) \
652 *(thousand) = *(unsigned char*)lv->thousands_sep; \
656 #endif /*!defined(SFSETLOCALE) && _lib_locale*/
658 #if !defined(SFSETLOCALE)
659 #define SFSETLOCALE(decimal,thousand) (*(decimal)='.')
662 /* stream pool structure. */
663 typedef struct _sfpool_s Sfpool_t
;
666 int mode
; /* type of pool */
667 int s_sf
; /* size of pool array */
668 int n_sf
; /* number currently in pool */
669 Sfio_t
** sf
; /* array of streams */
670 Sfio_t
* array
[3]; /* start with 3 */
671 Vtmutex_t mutex
; /* mutex lock object */
674 /* reserve buffer structure */
675 typedef struct _sfrsrv_s Sfrsrv_t
;
677 { ssize_t slen
; /* last string length */
678 ssize_t size
; /* buffer size */
679 uchar data
[1]; /* data buffer */
682 /* co-process structure */
683 typedef struct _sfproc_s Sfproc_t
;
685 { int pid
; /* process id */
686 uchar
* rdata
; /* read data being cached */
687 int ndata
; /* size of cached data */
688 int size
; /* buffer size */
689 int file
; /* saved file descriptor */
690 int sigp
; /* sigpipe protection needed */
693 /* extensions to sfvprintf/sfvscanf */
694 #define FP_SET(fp,fn) (fp < 0 ? (fn += 1) : (fn = fp) )
700 #define FP_INDEX 5 /* index size */
702 typedef struct _fmt_s Fmt_t
;
703 typedef struct _fmtpos_s Fmtpos_t
;
721 uchar uc
, *us
, **usp
;
727 { char* form
; /* format string */
728 va_list args
; /* corresponding arglist */
729 SFMBDCL(mbs
) /* multibyte parsing state */
731 char* oform
; /* original format string */
732 va_list oargs
; /* original arg list */
733 int argn
; /* number of args already used */
734 Fmtpos_t
* fp
; /* position list */
736 Sffmt_t
* ft
; /* formatting environment */
737 Sffmtevent_f eventf
; /* event function */
738 Fmt_t
* next
; /* stack frame pointer */
742 { Sffmt_t ft
; /* environment */
743 Argv_t argv
; /* argument value */
744 int fmt
; /* original format */
745 int need
[FP_INDEX
]; /* positions depending on */
756 #define FMTSET(ft, frm,ags, fv, sz, flgs, wid,pr,bs, ts,ns) \
757 ((ft->form = (char*)frm), va_copy(ft->args,ags), \
758 (ft->fmt = fv), (ft->size = sz), \
759 (ft->flags = (flgs&SFFMT_SET)), \
760 (ft->width = wid), (ft->precis = pr), (ft->base = bs), \
761 (ft->t_str = ts), (ft->n_str = ns) )
762 #define FMTGET(ft, frm,ags, fv, sz, flgs, wid,pr,bs) \
763 ((frm = ft->form), va_copy(ags,ft->args), \
764 (fv = ft->fmt), (sz = ft->size), \
765 (flgs = (flgs&~(SFFMT_SET))|(ft->flags&SFFMT_SET)), \
766 (wid = ft->width), (pr = ft->precis), (bs = ft->base) )
768 /* format flags&types, must coexist with those in sfio.h */
769 #define SFFMT_FORBIDDEN 000077777777 /* for sfio.h only */
770 #define SFFMT_EFORMAT 001000000000 /* sfcvt converting %e */
771 #define SFFMT_MINUS 002000000000 /* minus sign */
772 #define SFFMT_AFORMAT 004000000000 /* sfcvt converting %a */
773 #define SFFMT_UPPER 010000000000 /* sfcvt converting upper */
775 #define SFFMT_TYPES (SFFMT_SHORT|SFFMT_SSHORT | SFFMT_LONG|SFFMT_LLONG|\
776 SFFMT_LDOUBLE | SFFMT_IFLAG|SFFMT_JFLAG| \
777 SFFMT_TFLAG | SFFMT_ZFLAG )
779 /* type of elements to be converted */
780 #define SFFMT_INT 001 /* %d,%i */
781 #define SFFMT_UINT 002 /* %u,o,x etc. */
782 #define SFFMT_FLOAT 004 /* %f,e,g etc. */
783 #define SFFMT_CHAR 010 /* %c,C */
784 #define SFFMT_POINTER 020 /* %p,n,s,S */
785 #define SFFMT_CLASS 040 /* %[ */
787 /* local variables used across sf-functions */
788 #define _Sfpage (_Sfextern.sf_page)
789 #define _Sfpool (_Sfextern.sf_pool)
790 #define _Sfpmove (_Sfextern.sf_pmove)
791 #define _Sfstack (_Sfextern.sf_stack)
792 #define _Sfnotify (_Sfextern.sf_notify)
793 #define _Sfstdsync (_Sfextern.sf_stdsync)
794 #define _Sfudisc (&(_Sfextern.sf_udisc))
795 #define _Sfcleanup (_Sfextern.sf_cleanup)
796 #define _Sfexiting (_Sfextern.sf_exiting)
797 #define _Sfdone (_Sfextern.sf_done)
798 #define _Sfonce (_Sfextern.sf_once)
799 #define _Sfoncef (_Sfextern.sf_oncef)
800 #define _Sfmutex (_Sfextern.sf_mutex)
801 typedef struct _sfextern_s
803 struct _sfpool_s sf_pool
;
804 int (*sf_pmove
)_ARG_((Sfio_t
*, int));
805 Sfio_t
* (*sf_stack
)_ARG_((Sfio_t
*, Sfio_t
*));
806 void (*sf_notify
)_ARG_((Sfio_t
*, int, void*));
807 int (*sf_stdsync
)_ARG_((Sfio_t
*));
808 struct _sfdisc_s sf_udisc
;
809 void (*sf_cleanup
)_ARG_((void));
813 void (*sf_oncef
)_ARG_((void));
817 /* get the real value of a byte in a coded long or ulong */
818 #define SFUVALUE(v) (((ulong)(v))&(SF_MORE-1))
819 #define SFSVALUE(v) ((( long)(v))&(SF_SIGN-1))
820 #define SFBVALUE(v) (((ulong)(v))&(SF_BYTE-1))
822 /* pick this many bits in each iteration of double encoding */
825 /* grain size for buffer increment */
826 #define SF_GRAIN 1024
827 #define SF_PAGE ((ssize_t)(SF_GRAIN*sizeof(int)*2))
829 /* when the buffer is empty, certain io requests may be better done directly
830 on the given application buffers. The below condition determines when.
832 #define SFDIRECT(f,n) (((ssize_t)(n) >= (f)->size) || \
833 ((n) >= SF_GRAIN && (ssize_t)(n) >= (f)->size/16 ) )
835 /* number of pages to memory map at a time */
839 #define MAP_VARIABLE 0
842 #define _mmap_fixed 0
845 /* set/unset sequential states for mmap */
846 #if _lib_madvise && defined(MADV_SEQUENTIAL) && defined(MADV_NORMAL)
847 #define SFMMSEQON(f,a,s) \
848 do { int oerrno = errno; \
849 (void)madvise((caddr_t)(a),(size_t)(s),MADV_SEQUENTIAL); \
852 #define SFMMSEQOFF(f,a,s) \
853 do { int oerrno = errno; \
854 (void)madvise((caddr_t)(a),(size_t)(s),MADV_NORMAL); \
858 #define SFMMSEQON(f,a,s)
859 #define SFMMSEQOFF(f,a,s)
862 #define SFMUNMAP(f,a,s) (sysmunmapf((caddr_t)(a),(size_t)(s)), \
863 ((f)->endb = (f)->endr = (f)->endw = (f)->next = \
864 (f)->data = NIL(uchar*)) )
866 /* safe closing function */
867 #define CLOSE(f) { while(sysclosef(f) < 0 && errno == EINTR) errno = 0; }
869 /* the bottomless bit bucket */
870 #define DEVNULL "/dev/null"
871 #define SFSETNULL(f) ((f)->extent = (Sfoff_t)(-1), (f)->bits |= SF_NULL)
872 #define SFISNULL(f) ((f)->extent < 0 && ((f)->bits&SF_NULL) )
874 #define SFKILL(f) ((f)->mode = (SF_AVAIL|SF_LOCK) )
875 #define SFKILLED(f) (((f)->mode&(SF_AVAIL|SF_LOCK)) == (SF_AVAIL|SF_LOCK) )
877 /* exception types */
878 #define SF_EDONE 0 /* stop this operation and return */
879 #define SF_EDISC 1 /* discipline says it's ok */
880 #define SF_ESTACK 2 /* stack was popped */
881 #define SF_ECONT 3 /* can continue normally */
883 #define SETLOCAL(f) ((f)->mode |= SF_LOCAL)
884 #define GETLOCAL(f,v) ((v) = ((f)->mode&SF_LOCAL), (f)->mode &= ~SF_LOCAL, (v))
885 #define SFWRALL(f) ((f)->mode |= SF_RV)
886 #define SFISALL(f,v) ((((v) = (f)->mode&SF_RV) ? ((f)->mode &= ~SF_RV) : 0), \
887 ((v) || ((f)->flags&(SF_SHARE|SF_APPENDWR|SF_WHOLE)) ) )
888 #define SFSK(f,a,o,d) (SETLOCAL(f),sfsk(f,(Sfoff_t)a,o,d))
889 #define SFRD(f,b,n,d) (SETLOCAL(f),sfrd(f,(Void_t*)b,n,d))
890 #define SFWR(f,b,n,d) (SETLOCAL(f),sfwr(f,(Void_t*)b,n,d))
891 #define SFSYNC(f) (SETLOCAL(f),sfsync(f))
892 #define SFCLOSE(f) (SETLOCAL(f),sfclose(f))
893 #define SFFLSBUF(f,n) (SETLOCAL(f),_sfflsbuf(f,n))
894 #define SFFILBUF(f,n) (SETLOCAL(f),_sffilbuf(f,n))
895 #define SFSETBUF(f,s,n) (SETLOCAL(f),sfsetbuf(f,s,n))
896 #define SFWRITE(f,s,n) (SETLOCAL(f),sfwrite(f,s,n))
897 #define SFREAD(f,s,n) (SETLOCAL(f),sfread(f,s,n))
898 #define SFSEEK(f,p,t) (SETLOCAL(f),sfseek(f,p,t))
899 #define SFNPUTC(f,c,n) (SETLOCAL(f),sfnputc(f,c,n))
900 #define SFRAISE(f,e,d) (SETLOCAL(f),sfraise(f,e,d))
902 /* lock/open a stream */
903 #define SFMODE(f,l) ((f)->mode & ~(SF_RV|SF_RC|((l) ? SF_LOCK : 0)) )
904 #define SFLOCK(f,l) (void)((f)->mode |= SF_LOCK, (f)->endr = (f)->endw = (f)->data)
905 #define _SFOPENRD(f) ((f)->endr = ((f)->flags&SF_MTSAFE) ? (f)->data : (f)->endb)
906 #define _SFOPENWR(f) ((f)->endw = ((f)->flags&(SF_MTSAFE|SF_LINE)) ? (f)->data : (f)->endb)
907 #define _SFOPEN(f) ((f)->mode == SF_READ ? _SFOPENRD(f) : \
908 (f)->mode == SF_WRITE ? _SFOPENWR(f) : \
909 ((f)->endw = (f)->endr = (f)->data) )
910 #define SFOPEN(f,l) (void)((l) ? 0 : \
911 ((f)->mode &= ~(SF_LOCK|SF_RC|SF_RV), _SFOPEN(f), 0) )
913 /* check to see if the stream can be accessed */
914 #define SFFROZEN(f) (((f)->mode&(SF_PUSH|SF_LOCK|SF_PEEK)) ? 1 : \
915 !((f)->mode&SF_STDIO) ? 0 : \
916 _Sfstdsync ? (*_Sfstdsync)(f) : (((f)->mode &= ~SF_STDIO),0) )
919 /* set discipline code */
920 #define SFDISC(f,dc,iof) \
923 d = (dc) = (f)->disc; \
924 else d = (f->bits&SF_DCDOWN) ? ((dc) = (dc)->disc) : (dc); \
925 while(d && !(d->iof)) d = d->disc; \
928 #define SFDCRD(f,buf,n,dc,rv) \
929 { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
930 rv = (*dc->readf)(f,buf,n,dc); \
931 if(!dcdown) f->bits &= ~SF_DCDOWN; \
933 #define SFDCWR(f,buf,n,dc,rv) \
934 { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
935 rv = (*dc->writef)(f,buf,n,dc); \
936 if(!dcdown) f->bits &= ~SF_DCDOWN; \
938 #define SFDCSK(f,addr,type,dc,rv) \
939 { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
940 rv = (*dc->seekf)(f,addr,type,dc); \
941 if(!dcdown) f->bits &= ~SF_DCDOWN; \
944 /* fast peek of a stream */
945 #define _SFAVAIL(f,s,n) ((n) = (f)->endb - ((s) = (f)->next) )
946 #define SFRPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \
947 ((n) = SFFILBUF(f,-1), (s) = (f)->next, (n)) )
948 #define SFWPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \
949 ((n) = SFFLSBUF(f,-1), (s) = (f)->next, (n)) )
951 /* more than this for a line buffer, we might as well flush */
952 #define HIFORLINE 128
954 /* string stream extent */
955 #define SFSTRSIZE(f) { Sfoff_t s = (f)->next - (f)->data; \
957 { (f)->here = s; if(s > (f)->extent) (f)->extent = s; } \
960 /* control flags for open() */
962 #define _has_oflags 1
963 #else /* for example, research UNIX */
964 #define _has_oflags 0
988 #define O_TEMPORARY 000
991 #define SF_RADIX 64 /* maximum integer conversion base */
994 #define SF_MAXINT INT_MAX
995 #define SF_MAXLONG LONG_MAX
997 #define SF_MAXINT ((int)(((uint)~0) >> 1))
998 #define SF_MAXLONG ((long)(((ulong)~0L) >> 1))
1001 #define SF_MAXCHAR ((uchar)(~0))
1003 /* floating point to ascii conversion */
1004 #define SF_MAXEXP10 6
1005 #define SF_MAXPOW10 (1 << SF_MAXEXP10)
1006 #if !_ast_fltmax_double
1007 #define SF_FDIGITS 1024 /* max allowed fractional digits */
1008 #define SF_IDIGITS (8*1024) /* max number of digits in int part */
1010 #define SF_FDIGITS 256 /* max allowed fractional digits */
1011 #define SF_IDIGITS 1024 /* max number of digits in int part */
1013 #define SF_MAXDIGITS (((SF_FDIGITS+SF_IDIGITS)/sizeof(int) + 1)*sizeof(int))
1015 /* tables for numerical translation */
1016 #define _Sfpos10 (_Sftable.sf_pos10)
1017 #define _Sfneg10 (_Sftable.sf_neg10)
1018 #define _Sfdec (_Sftable.sf_dec)
1019 #define _Sfdigits (_Sftable.sf_digits)
1020 #define _Sfcvinitf (_Sftable.sf_cvinitf)
1021 #define _Sfcvinit (_Sftable.sf_cvinit)
1022 #define _Sffmtposf (_Sftable.sf_fmtposf)
1023 #define _Sffmtintf (_Sftable.sf_fmtintf)
1024 #define _Sfcv36 (_Sftable.sf_cv36)
1025 #define _Sfcv64 (_Sftable.sf_cv64)
1026 #define _Sftype (_Sftable.sf_type)
1027 #define _Sfieee (&_Sftable.sf_ieee)
1028 #define _Sffinf (_Sftable.sf_ieee.fltinf)
1029 #define _Sfdinf (_Sftable.sf_ieee.dblinf)
1030 #define _Sflinf (_Sftable.sf_ieee.ldblinf)
1031 #define _Sffnan (_Sftable.sf_ieee.fltnan)
1032 #define _Sfdnan (_Sftable.sf_ieee.dblnan)
1033 #define _Sflnan (_Sftable.sf_ieee.ldblnan)
1034 #define _Sffpow10 (_Sftable.sf_flt_pow10)
1035 #define _Sfdpow10 (_Sftable.sf_dbl_pow10)
1036 #define _Sflpow10 (_Sftable.sf_ldbl_pow10)
1037 typedef struct _sfieee_s Sfieee_t
;
1039 { float fltnan
; /* float NAN */
1040 float fltinf
; /* float INF */
1041 double dblnan
; /* double NAN */
1042 double dblinf
; /* double INF */
1043 Sfdouble_t ldblnan
; /* Sfdouble_t NAN */
1044 Sfdouble_t ldblinf
; /* Sfdouble_t INF */
1046 typedef struct _sftab_
1047 { Sfdouble_t sf_pos10
[SF_MAXEXP10
]; /* positive powers of 10 */
1048 Sfdouble_t sf_neg10
[SF_MAXEXP10
]; /* negative powers of 10 */
1049 uchar sf_dec
[200]; /* ascii reps of values < 100 */
1050 char* sf_digits
; /* digits for general bases */
1051 int (*sf_cvinitf
)(); /* initialization function */
1052 int sf_cvinit
; /* initialization state */
1053 Fmtpos_t
* (*sf_fmtposf
)_ARG_((Sfio_t
*,const char*,va_list,Sffmt_t
*,int));
1054 char* (*sf_fmtintf
)_ARG_((const char*,int*));
1055 float* sf_flt_pow10
; /* float powers of 10 */
1056 double* sf_dbl_pow10
; /* double powers of 10 */
1057 Sfdouble_t
* sf_ldbl_pow10
; /* Sfdouble_t powers of 10 */
1058 uchar sf_cv36
[SF_MAXCHAR
+1]; /* conversion for base [2-36] */
1059 uchar sf_cv64
[SF_MAXCHAR
+1]; /* conversion for base [37-64] */
1060 uchar sf_type
[SF_MAXCHAR
+1]; /* conversion formats&types */
1061 Sfieee_t sf_ieee
; /* IEEE floating point constants*/
1064 /* thread-safe macro/function to initialize _Sfcv* conversion tables */
1065 #define SFCVINIT() (_Sfcvinit ? 1 : (_Sfcvinit = (*_Sfcvinitf)()) )
1067 /* sfucvt() converts decimal integers to ASCII */
1068 #define SFDIGIT(v,scale,digit) \
1073 else { digit = '1'; v -= 1*scale; } \
1074 else if(v < 3*scale) \
1075 { digit = '2'; v -= 2*scale; } \
1076 else if(v < 4*scale) \
1077 { digit = '3'; v -= 3*scale; } \
1078 else { digit = '4'; v -= 4*scale; } \
1079 else if(v < 7*scale) \
1081 { digit = '5'; v -= 5*scale; } \
1082 else { digit = '6'; v -= 6*scale; } \
1083 else if(v < 8*scale) \
1084 { digit = '7'; v -= 7*scale; } \
1085 else if(v < 9*scale) \
1086 { digit = '8'; v -= 8*scale; } \
1087 else { digit = '9'; v -= 9*scale; } \
1089 #define sfucvt(v,s,n,list,type,utype) \
1090 { while((utype)v >= 10000) \
1091 { n = v; v = (type)(((utype)v)/10000); \
1092 n = (type)((utype)n - ((utype)v)*10000); \
1093 s -= 4; SFDIGIT(n,1000,s[0]); SFDIGIT(n,100,s[1]); \
1094 s[2] = *(list = (char*)_Sfdec + (n <<= 1)); s[3] = *(list+1); \
1098 { s -= 1; s[0] = (char)('0'+v); \
1100 { s -= 2; s[0] = *(list = (char*)_Sfdec + (v <<= 1)); s[1] = *(list+1); \
1104 { s -= 3; SFDIGIT(v,100,s[0]); \
1105 s[1] = *(list = (char*)_Sfdec + (v <<= 1)); s[2] = *(list+1); \
1107 { s -= 4; SFDIGIT(v,1000,s[0]); SFDIGIT(v,100,s[1]); \
1108 s[2] = *(list = (char*)_Sfdec + (v <<= 1)); s[3] = *(list+1); \
1113 /* handy functions */
1116 #define min(x,y) ((x) < (y) ? (x) : (y))
1117 #define max(x,y) ((x) > (y) ? (x) : (y))
1119 /* fast functions for memory copy and memory clear */
1121 #define memclear(s,n) memzero(s,n)
1123 #if _lib_bcopy && !_lib_memcpy
1124 #define memcpy(to,fr,n) bcopy((fr),(to),(n))
1126 #if _lib_bzero && !_lib_memset
1127 #define memclear(s,n) bzero((s),(n))
1129 #define memclear(s,n) memset((s),'\0',(n))
1131 #endif /*_PACKAGE_ast*/
1133 /* note that MEMCPY advances the associated pointers */
1134 #define MEMCPY(to,fr,n) \
1136 { default : memcpy((Void_t*)to,(Void_t*)fr,n); to += n; fr += n; break; \
1137 case 7 : *to++ = *fr++; \
1138 case 6 : *to++ = *fr++; \
1139 case 5 : *to++ = *fr++; \
1140 case 4 : *to++ = *fr++; \
1141 case 3 : *to++ = *fr++; \
1142 case 2 : *to++ = *fr++; \
1143 case 1 : *to++ = *fr++; \
1145 #define MEMSET(s,c,n) \
1147 { default : memset((Void_t*)s,(int)c,n); s += n; break; \
1148 case 7 : *s++ = c; \
1149 case 6 : *s++ = c; \
1150 case 5 : *s++ = c; \
1151 case 4 : *s++ = c; \
1152 case 3 : *s++ = c; \
1153 case 2 : *s++ = c; \
1154 case 1 : *s++ = c; \
1159 extern Sftab_t _Sftable
;
1161 extern int _sfpopen
_ARG_((Sfio_t
*, int, int, int));
1162 extern int _sfpclose
_ARG_((Sfio_t
*));
1163 extern int _sfexcept
_ARG_((Sfio_t
*, int, ssize_t
, Sfdisc_t
*));
1164 extern Sfrsrv_t
* _sfrsrv
_ARG_((Sfio_t
*, ssize_t
));
1165 extern int _sfsetpool
_ARG_((Sfio_t
*));
1166 extern char* _sfcvt
_ARG_((Void_t
*,char*,size_t,int,int*,int*,int*,int));
1167 extern char** _sfgetpath
_ARG_((char*));
1169 #if _BLD_sfio && defined(__EXPORT__)
1170 #define extern __EXPORT__
1172 #if !_BLD_sfio && defined(__IMPORT__)
1173 #define extern extern __IMPORT__
1176 extern Sfextern_t _Sfextern
;
1178 extern int _sfmode
_ARG_((Sfio_t
*, int, int));
1179 extern int _sftype
_ARG_((const char*, int*, int*));
1187 /* for portable encoding of double values */
1189 #if _ast_fltmax_double
1190 #define frexpl frexp
1193 extern Sfdouble_t frexpl
_ARG_((Sfdouble_t
, int*));
1197 #if _ast_fltmax_double
1198 #define ldexpl ldexp
1201 extern Sfdouble_t ldexpl
_ARG_((Sfdouble_t
, int));
1207 #if !__STDC__ && !_hdr_stdlib
1208 extern void abort
_ARG_((void));
1209 extern int atexit
_ARG_((void(*)(void)));
1210 extern char* getenv
_ARG_((const char*));
1211 extern void* malloc
_ARG_((size_t));
1212 extern void* realloc
_ARG_((void*, size_t));
1213 extern void free
_ARG_((void*));
1214 extern size_t strlen
_ARG_((const char*));
1215 extern char* strcpy
_ARG_((char*, const char*));
1217 extern Void_t
* memset
_ARG_((void*, int, size_t));
1218 extern Void_t
* memchr
_ARG_((const void*, int, size_t));
1219 extern Void_t
* memccpy
_ARG_((void*, const void*, int, size_t));
1221 extern Void_t
* memcpy
_ARG_((void*, const void*, size_t));
1223 #if !defined(strtod)
1224 extern double strtod
_ARG_((const char*, char**));
1226 #if !defined(remove)
1227 extern int sysremovef
_ARG_((const char*));
1229 #endif /* !__STDC__ && !_hdr_stdlib */
1232 #if _proto_open && __cplusplus
1233 extern int sysopenf
_ARG_((const char*, int, ...));
1235 extern int sysclosef
_ARG_((int));
1236 extern ssize_t sysreadf
_ARG_((int, void*, size_t));
1237 extern ssize_t syswritef
_ARG_((int, const void*, size_t));
1238 extern sfoff_t syslseekf
_ARG_((int, sfoff_t
, int));
1239 extern int sysdupf
_ARG_((int));
1240 extern int syspipef
_ARG_((int*));
1241 extern int sysaccessf
_ARG_((const char*, int));
1242 extern int sysremovef
_ARG_((const char*));
1243 extern int sysfstatf
_ARG_((int, sfstat_t
*));
1244 extern int sysstatf
_ARG_((const char*, sfstat_t
*));
1246 extern int isatty
_ARG_((int));
1248 extern int wait
_ARG_((int*));
1249 extern uint sleep
_ARG_((uint
));
1250 extern int execl
_ARG_((const char*, const char*,...));
1251 extern int execv
_ARG_((const char*, char**));
1253 extern int fork
_ARG_((void));
1256 extern int unlink
_ARG_((const char*));
1259 #endif /*_hdr_unistd*/
1261 #if _lib_bcopy && !_proto_bcopy
1262 extern void bcopy
_ARG_((const void*, void*, size_t));
1264 #if _lib_bzero && !_proto_bzero
1265 extern void bzero
_ARG_((void*, size_t));
1268 extern time_t time
_ARG_((time_t*));
1269 extern int waitpid
_ARG_((int,int*,int));
1270 extern void _exit
_ARG_((int));
1271 typedef int(* Onexit_f
)_ARG_((void));
1272 extern Onexit_f onexit
_ARG_((Onexit_f
));
1274 #if _lib_vfork && !_hdr_vfork && !_sys_vfork
1275 extern pid_t vfork
_ARG_((void));
1276 #endif /*_lib_vfork*/
1280 extern int poll
_ARG_((struct pollfd
*, ulong
, int));
1282 extern int poll
_ARG_((ulong
, struct pollfd
*, int));
1284 #endif /*_lib_poll*/
1286 #endif /* _PACKAGE_ast */