##################################################################
# This file defines probes for local features that sfio requires.
# Such probes are interpreted by the "iffe" language interpreter.
# Results are stored in the FEATURE directory.
# Written by Kiem-Phong Vo (06/27/92).
# Converted to sfio v10/01/94 by Giampiero Sierra (06/08/95).
##################################################################

lib atexit,onexit,on_exit

exit    cleanup note{ stuck with standard _cleanup }end execute{
        #include <stdio.h>
        _BEGIN_EXTERNS_
        extern void exit _ARG_((int));
        extern void _exit _ARG_((int));
        extern void _cleanup();
        void _cleanup() { _exit(0); }
        _END_EXTERNS_
        main() { printf("cleanup\n"); exit(1); }
}end

lib bcopy,bzero,memccpy,memchr
sys types
hdr time

sys stat note{ stat() in default lib(s) }end compile{
	#if _STD_
	#include	<stddef.h>
	#else
	#include	<sys/types.h>
	#endif
	#include	<time.h>
	#include	<sys/stat.h>
	main() { int s = (int)sizeof(struct stat); }
}end

hdr stat compile{
	#if _STD_
	#include	<stddef.h>
	#else
	#include	<sys/types.h>
	#endif
	#include	<time.h>
	#include	<stat.h>
	main() { int s = (int)sizeof(struct stat); }
}end

##################################################
# Tests for  memory mapping
##################################################

sys mman

tst     lib_mmap sys/types.h sys/stat.h unistd.h fcntl.h mman.h sys/mman.h sys/times.h note{ standard mmap interface that works }end execute{
        #define BUFSIZE (16*1024)
        #define MAPSIZE (16*1024)
        #define WRITE   (64)
        #if _STD_
        main(int argc, char** argv)
        #else
        main(argc,argv)
        int     argc;
        char**  argv;
        #endif
        {
                caddr_t         mm;
                char*           t;
                char*           f;
                int             i;
                int             fd;
                char            file[1024];
                char            buf[BUFSIZE];
                struct tms      brdtm, erdtm, bmmtm, emmtm;
		clock_t		rdtm, mmtm;

                f = argv[0];
                t = file;
                while (*t = *f++) t++;
                *t++ = '.';
                *t++ = 'D';
                *t = 0;
                /* create data file */
                if ((fd = creat(file,0666)) < 0)
                        return(1);
                for (i = 0; i < sizeof(buf); ++i)
                        buf[i] = '0' + (i%10);
                for (i = 0; i < WRITE; ++i)
                        if (write(fd,buf,sizeof(buf)) != sizeof(buf))
                                return(1);
                close(fd);
                /* read time */
                if ((fd = open(file, 0)) < 0)
                        return(1);
                times(&brdtm);
                for (i = 0; i < WRITE; ++i)
                        if (read(fd,buf,sizeof(buf)) != sizeof(buf))
                                return(1);
                times(&erdtm);
                close(fd);
                /* memory map time */
                if ((fd = open(file,0)) < 0)
                        return(1);
                times(&bmmtm);
                mm = 0;
                for (i = 0; i < (WRITE/(MAPSIZE/BUFSIZE)); ++i)
                {       mm = (caddr_t)mmap(mm, MAPSIZE, (PROT_READ|PROT_WRITE),
                                  (MAP_PRIVATE | (mm ? MAP_FIXED : 0)),
                                  fd, i*MAPSIZE );
                        if(mm == (caddr_t)(-1) || mm == (caddr_t)0)
                                return(1);
                }
                times(&emmtm);
                close(fd);
                unlink(file);
#define SLOP	60
                rdtm =	(erdtm.tms_utime-brdtm.tms_utime) +
			(erdtm.tms_stime-brdtm.tms_stime) + SLOP;
                mmtm =	(emmtm.tms_utime-bmmtm.tms_utime) +
			(emmtm.tms_stime-bmmtm.tms_stime);
		if(rdtm < mmtm)
                        return(1);

                return(0);
        }
}end

##################################################
# vfork and any associated header files
##################################################

hdr vfork
sys vfork
lib vfork

pragma vfork note{ pragma vfork ok }end compile{
	_BEGIN_EXTERNS_
	extern int	vfork();
	_END_EXTERNS_
	#pragma unknown_control_flow(vfork)
	main() { return vfork() >= 0 ? 0 : -1; }
}end
	
##################################################
# file control checks
##################################################

hdr filio
sys filio,ioctl
lib mktemp,remove,unlink
lib waitpid
lib getpagesize

typ long_double excecute{
	main() { 
	long double d = 0; 
	return sizeof(long double) > sizeof(double) ? 0 : 1; 
	}
}end

##################################################
# See if the preferred block size for a file system can be found
##################################################

stat blksize compile{
	#include	<sys/types.h>
	#include	<sys/stat.h>
	main () {
		struct stat sb;
		sb.st_blksize = 0;
		return 0;
	}
}end

##################################################
# check to see if certain prototypes are required
##################################################

proto open compile{
	#include	<sys/types.h>
	#include	<errno.h>
	#include	<ctype.h>
	#include	<fcntl.h>

	_BEGIN_EXTERNS_
	extern int open _ARG_((const char*,int,...));
	_END_EXTERNS_
	main()
	{
		open("file",0);
		open("file",0,1);
	}
}end

pragma weak link{
	main() { return _xyz(); }
	#pragma weak   _xyz =  __xyz
	#define                _xyz    __xyz
	_xyz() { return 0; }
}end


################################################
## Revision note:  Return value has changed
################################################

lib     poll_fd_1 note{ fd is first arg to poll() }end execute{
        #include <poll.h>
        _BEGIN_EXTERNS_
        extern int      pipe _ARG_((int*));
        _END_EXTERNS_
        main()
        {       int             rw[2];
                struct pollfd   fd;
                if (pipe(rw) < 0) return 1;
                fd.fd = rw[0];
                fd.events = POLLIN;
                fd.revents = 0;
                return poll(&fd, 1, 0) < 0;
        }
}end

################################################
## Revision note:  Return value has changed
################################################

lib     poll_fd_2 note{ fd is second arg to poll() }end execute{
        #include <poll.h>
        _BEGIN_EXTERNS_
        extern int      pipe _ARG_((int*));
        _END_EXTERNS_
        main()
        {       int             rw[2];
                struct pollfd   fd;
                if (pipe(rw) < 0) return 1;
                fd.fd = rw[0];
                fd.events = POLLIN;
                fd.revents = 0;
                return poll(1, &fd, 0) < 0;
        }
}end

################################################
## Revision note:  This has gone from 'compile' to 'link'
################################################

lib	select note{ select() has standard 5 arg interface }end link{
	#include <sys/types.h>
        #include <sys/time.h>
        #include <sys/socket.h>
        main()
        {       struct timeval  tmb;
                fd_set          rd;
                FD_ZERO(&rd);
                FD_SET(0,&rd);
                tmb.tv_sec = 0;
                tmb.tv_usec = 0;
                select(1,&rd,(fd_set*)0,(fd_set*)0,&tmb);
                return 0;
        }
}end

################################################################
## See if we can peek ahead in unseekable devices
################################################################

stream	peek note{ ioctl(I_PEEK) works }end link{
        #include <sys/types.h>
        #include <stropts.h>
        main()
        {       struct strpeek  pbuf;
                pbuf.flags = 0;
                pbuf.ctlbuf.maxlen = pbuf.databuf.maxlen =
                pbuf.ctlbuf.len = pbuf.databuf.len = 0;
                pbuf.ctlbuf.buf = pbuf.databuf.buf = 0;
                ioctl(0,I_PEEK,&pbuf);
                return 0;
        }
}end

socket	peek note{ recv(MSG_PEEK) works }end link{
        #include <sys/types.h>
        #include <sys/socket.h>
        main()
        {       char    buf[128];
                recv(0,buf,sizeof(buf),MSG_PEEK);
                return 0;
        }
}end


################################################################
## See if register layout is ok for vax string operations
################################################################

vax asm note{ register layout ok for vax string operations }end execute{
        main()
        {
        #ifndef vax
                return absurd = -1;
        #else
                register int    r11, r10, r9, r8, r7, r6;
                r11 = r10 = r9 = r8 = r7 = r6 = -1;
                asm("clrw       r11");
                asm("clrw       r10");
                asm("clrw       r9");
                asm("clrw       r8");
                asm("clrw       r7");
                asm("clrw       r6");
                if(sizeof(int) != sizeof(char*) || r11 || r10 || r9 || r8 || r7 || r6 )
                        return -1;
                return 0;
        #endif
        }
}end

################################################################
## 386 native floating point conversions are better than what we can do in C
################################################################

################################################
## Revision note:  This has gone from 'compile' to 'link'
################################################

i386 cvt note{ 386 native floating point conversions better than C }end link{
        main()
        {
        #ifndef i386
                return absurd = -1;
        #else
                ecvt();
                fcvt();
                strtod();
                return 0;
        #endif
        }
}end

################################################################
## Check to see if there is "locale" stuff for conditioning printf/scanf
################################################################

lib locale note{ Check for localeconv }end compile{
	#include	<locale.h>
	main()
	{	struct lconv* lv = localeconv();
		return 0;
	}
}end

########################################
## Note:  The following lines are also no longer needed
########################################

#:endgroup:sfio
#:group:stdio:Configuration parameters for stdio-binary-compatible functions

################################################################
## for generating the stdio binary compatibility package
################################################################

FILE cnt note{ 1 if the field "_cnt" exists in the FILE structure }end compile{
	#include	<stdio.h>
	main() { return (stdin->_cnt == 0) ? 0 : -1; }
}end

FILE ptr note{ 1 if the field "_ptr" exists in the FILE structure }end compile{
	#include	<stdio.h>
	main() { return (stdin->_ptr == 0) ? 0 : -1; }
}end

FILE file note{ 1 if the field "_file" exists in the FILE structure }end compile{
	#include	<stdio.h>
	main() { return (stdin->_file == 0) ? 0 : -1; }
}end

FILE flag note{ 1 if the field "_flag" exists in the FILE structure }end compile{
	#include	<stdio.h>
	main() { return (stdin->_flag != 0) ? 0 : -1; }
}end

FILE base note{ 1 if the field "_base" exists in the FILE structure }end compile{
	#include	<stdio.h>
	main() { return sizeof(stdin->_base) == sizeof(char*) ? 0 : -1; }
}end

FILE bufsize note{ 1 if "_bufsize" exists and as large as a pointer }end excecute{
	#include	<stdio.h>
	main() { return sizeof(stdin->_bufsize) == sizeof(char*) ? 0 : -1; }
}end

FILE bufsiz note{ 1 if "_bufsiz" exists and as large as a pointer }end excecute{
	#include	<stdio.h>
	main() { return sizeof(stdin->_bufsiz) == sizeof(char*) ? 0 : -1; }
}end

#:endgroup:stdio
