814 lines
22 KiB
C
814 lines
22 KiB
C
/* s t d i o l i b
|
|
*
|
|
* (C) Copyright C E Chew
|
|
*
|
|
* Feel free to copy, use and distribute this software provided:
|
|
*
|
|
* 1. you do not pretend that you wrote it
|
|
* 2. you leave this copyright notice intact.
|
|
*
|
|
* This include file is used by the stdio code. It provides some
|
|
* useful macro definitions that make the code a bit easier to
|
|
* write.
|
|
*
|
|
* Patchlevel 3.0
|
|
*/
|
|
|
|
#ifndef STDIOLIB_H
|
|
#define STDIOLIB_H
|
|
|
|
#include "config.h"
|
|
|
|
/* Hide standard names */
|
|
|
|
#ifdef HIDDEN
|
|
# include "hidden.h"
|
|
#endif
|
|
|
|
/* System types */
|
|
|
|
#ifdef SYSTYPES
|
|
# include <sys/types.h>
|
|
#endif
|
|
|
|
/* Promotions for system call parameter passing */
|
|
|
|
#ifndef MODE_T
|
|
# define MODE_T int
|
|
#endif
|
|
|
|
#ifndef UID_T
|
|
# define UID_T int
|
|
#endif
|
|
|
|
/* System file control */
|
|
|
|
#include <fcntl.h>
|
|
|
|
/* Time types */
|
|
|
|
#ifdef TIME
|
|
# include <time.h>
|
|
#endif
|
|
|
|
/* Posix standard things */
|
|
|
|
#ifdef UNISTD
|
|
# include <unistd.h>
|
|
#endif
|
|
|
|
/* Limits */
|
|
|
|
#ifdef LIMITS
|
|
# include <limits.h>
|
|
#endif
|
|
|
|
/* Floating point limits */
|
|
|
|
#ifndef NOFLOAT
|
|
# ifdef FLOAT
|
|
# include <float.h>
|
|
# if DBL_MANT_DIG < LDBL_MANT_DIG && \
|
|
DBL_MAX_EXP < LDBL_MAX_EXP && \
|
|
DBL_MIN_EXP > LDBL_MIN_EXP
|
|
# define LONGDOUBLE
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
/* Long doubles */
|
|
|
|
#ifndef NOFLOAT
|
|
# ifdef LONGDOUBLE
|
|
typedef long double longdouble;
|
|
# define LMODF lmodf
|
|
# define LFREXP lfrexp
|
|
# define LLDEXP lldexp
|
|
# else
|
|
typedef double longdouble;
|
|
# define LMODF modf
|
|
# define LFREXP frexp
|
|
# define LLDEXP ldexp
|
|
# undef LDBL_DIG
|
|
# define LDBL_DIG DBL_DIG
|
|
# undef LDBL_EPSILON
|
|
# define LDBL_EPSILON DBL_EPSILON
|
|
# undef LDBL_MANT_DIG
|
|
# define LDBL_MANT_DIG DBL_MANT_DIG
|
|
# undef LDBL_MAX
|
|
# define LDBL_MAX DBL_MAX
|
|
# undef LDBL_MAX_10_EXP
|
|
# define LDBL_MAX_10_EXP DBL_MAX_10_EXP
|
|
# undef LDBL_MAX_EXP
|
|
# define LDBL_MAX_EXP DBL_MAX_EXP
|
|
# undef LDBL_MIN
|
|
# define LDBL_MIN DBL_MIN
|
|
# undef LDBL_MIN_10_EXP
|
|
# define LDBL_MIN_10_EXP DBL_MIN_10_EXP
|
|
# undef LDBL_MIN_EXP
|
|
# define LDBL_MIN_EXP DBL_MIN_EXP
|
|
# endif
|
|
#endif
|
|
|
|
/* Significant digits in mantissa
|
|
*
|
|
* Since 10^k = 5^k.2^k, the highest power of ten that will fit in N bits
|
|
* is N.log_5 2, if the exponent base if binary.
|
|
*/
|
|
|
|
#ifndef NOFLOAT
|
|
# if FLT_RADIX == 2
|
|
# define MANTDIGITS (LDBL_MANT_DIG * 1 * 43 / 100)
|
|
# define HALFMANTDIGITS (LDBL_MANT_DIG / 2 * 1 * 43 / 100)
|
|
# else
|
|
# if FLT_RADIX == 4
|
|
# define MANTDIGITS (LDBL_MANT_DIG * 2 * 43 / 100)
|
|
# define HALFMANTDIGITS (LDBL_MANT_DIG / 2 * 2 * 43 / 100)
|
|
# else
|
|
# if FLT_RADIX == 8
|
|
# define MANTDIGITS (LDBL_MANT_DIG * 3 * 43 / 100)
|
|
# define HALFMANTDIGITS (LDBL_MANT_DIG / 2 * 3 * 43 / 100)
|
|
# else
|
|
# if FLT_RADIX == 16
|
|
# define MANTDIGITS (LDBL_MANT_DIG * 4 * 43 / 100)
|
|
# define HALFMANTDIGITS (LDBL_MANT_DIG / 2 * 4 * 43 / 100)
|
|
# else
|
|
# if FLT_RADIX == 10
|
|
# define MANTDIGITS (LDBL_MANT_DIG)
|
|
# define HALFMANTDIGITS (LDBL_MANT_DIG/2)
|
|
# else
|
|
<< FLT_RADIX not on mantissa significant digits list >>
|
|
# endif
|
|
# endif
|
|
# endif
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
/* Constants */
|
|
|
|
#ifdef __STDC__
|
|
# define CONST const
|
|
#else
|
|
# define CONST
|
|
#endif
|
|
|
|
/* Variable argument list hiding */
|
|
|
|
#ifdef STDARG
|
|
# include <stdarg.h>
|
|
# define VA_START(n,l) va_start(n,l)
|
|
# ifdef __STDC__
|
|
# define VA_ALIST , ...
|
|
# else
|
|
# define VA_ALIST
|
|
# endif
|
|
# define VA_LIST va_list
|
|
# define VA_END(n) va_end(n)
|
|
# define VA_ARG(n,t) va_arg(n,t)
|
|
# define VA_DCL
|
|
#else
|
|
# include <varargs.h>
|
|
# define VA_START(n,l) va_start(n)
|
|
# define VA_ALIST va_alist
|
|
# define VA_LIST va_list
|
|
# define VA_END(n) va_end(n)
|
|
# define VA_ARG(n,t) va_arg(n,t)
|
|
# define VA_DCL va_dcl
|
|
#endif
|
|
|
|
/* Function prototype hiding */
|
|
|
|
#ifdef __STDC__
|
|
# define P(x) x
|
|
# define F8(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6,t7,n7,t8,n8) \
|
|
(t1 n1, t2 n2, t3 n3, t4 n4, t5 n5, t6 n6, t7 n7, t8 n8)
|
|
# define F7(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6,t7,n7) \
|
|
(t1 n1, t2 n2, t3 n3, t4 n4, t5 n5, t6 n6, t7 n7)
|
|
# define F6(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6) \
|
|
(t1 n1, t2 n2, t3 n3, t4 n4, t5 n5, t6 n6)
|
|
# define F5(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5) \
|
|
(t1 n1, t2 n2, t3 n3, t4 n4, t5 n5)
|
|
# define F4(t1,n1,t2,n2,t3,n3,t4,n4) \
|
|
(t1 n1, t2 n2, t3 n3, t4 n4)
|
|
# define F3(t1,n1,t2,n2,t3,n3) \
|
|
(t1 n1, t2 n2, t3 n3)
|
|
# define F2(t1,n1,t2,n2) \
|
|
(t1 n1, t2 n2)
|
|
# define F1(t1,n1) \
|
|
(t1 n1)
|
|
# define F0() (void)
|
|
#else
|
|
# define P(x) ()
|
|
# define F8(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6,t7,n7,t8,n8) \
|
|
(n1, n2, n3, n4, n5, n6, n7, n8) \
|
|
t1 n1;t2 n2;t3 n3;t4 n4;t5 n5;t6 n6;t7 n7;t8 n8;
|
|
# define F7(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6,t7,n7) \
|
|
(n1, n2, n3, n4, n5, n6, n7) \
|
|
t1 n1;t2 n2;t3 n3;t4 n4;t5 n5;t6 n6;t7 n7;
|
|
# define F6(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6) \
|
|
(n1, n2, n3, n4, n5, n6) \
|
|
t1 n1;t2 n2;t3 n3;t4 n4;t5 n5;t6 n6;
|
|
# define F5(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5) \
|
|
(n1, n2, n3, n4, n5) \
|
|
t1 n1;t2 n2;t3 n3;t4 n4;t5 n5;
|
|
# define F4(t1,n1,t2,n2,t3,n3,t4,n4) \
|
|
(n1, n2, n3, n4) \
|
|
t1 n1;t2 n2;t3 n3;t4 n4;
|
|
# define F3(t1,n1,t2,n2,t3,n3) \
|
|
(n1, n2, n3) \
|
|
t1 n1;t2 n2;t3 n3;
|
|
# define F2(t1,n1,t2,n2) \
|
|
(n1, n2) \
|
|
t1 n1;t2 n2;
|
|
# define F1(t1,n1) \
|
|
(n1) \
|
|
t1 n1;
|
|
# define F0() ()
|
|
#endif
|
|
|
|
/* Variadic function prototype hiding */
|
|
|
|
#ifdef STDARG
|
|
# ifdef __STDC__
|
|
# define F2V(t1,n1,t2,n2,t,a,l) \
|
|
(t1 n1, t2 n2 \
|
|
VA_ALIST) t a; l
|
|
# define F1V(t1,n1,t,a,l) \
|
|
(t1 n1 \
|
|
VA_ALIST) t a; l
|
|
# else
|
|
# define F2V(t1,n1,t2,n2,t,a,l) \
|
|
(n1,n2 VA_ALIST) \
|
|
t1 n1; t2 n2; \
|
|
t a; l
|
|
# define F1V(t1,n1,t,a,l) \
|
|
(n1 VA_ALIST) \
|
|
t1 n1; \
|
|
t a; l
|
|
# endif
|
|
#else
|
|
# define F2V(t1,n1,t2,n2,t,a,l) \
|
|
(VA_ALIST) VA_DCL \
|
|
t a; t1 n1;t2 n2; l \
|
|
n1 = VA_ARG(a,t1); \
|
|
n2 = VA_ARG(a,t2);
|
|
# define F1V(t1,n1,t,a,l) \
|
|
(VA_ALIST) VA_DCL \
|
|
t a; t1 n1; l \
|
|
n1 = VA_ARG(a,t1);
|
|
#endif
|
|
|
|
/* Strings */
|
|
|
|
#ifdef STRING
|
|
# include <string.h>
|
|
#endif
|
|
|
|
/* Memory */
|
|
|
|
#ifdef MEMORY
|
|
# define MEMCPY(d,s,n) ((void) memcpy((d),(s),(n)))
|
|
# define MEMCHR(s,c,n) (memchr((s),(c),(n)))
|
|
# define MEMSET(s,v,n) ((void) memset((s),(v),(n)))
|
|
# define MEMCCPY(d,s,c,n) (memccpy((d),(s),(c),(n)))
|
|
#endif
|
|
|
|
/* Unsigned char casting */
|
|
|
|
#ifdef UNSIGNEDCHAR
|
|
# define UCHAR(x) ((int) ((unsigned char) (x)))
|
|
#else
|
|
# define UCHAR(x) ((int) (x) & ((1 << CHAR_BIT) - 1))
|
|
#endif
|
|
|
|
/* Signal return type */
|
|
|
|
#include <signal.h>
|
|
|
|
#ifdef VOIDSIGNAL
|
|
typedef void (*signal_t) P((int));
|
|
#else
|
|
typedef int (*signal_t) P((int));
|
|
#endif
|
|
|
|
/* System error list */
|
|
|
|
#ifdef ERRLIST
|
|
/* Conditional referenced in _errlist.c */
|
|
#endif
|
|
|
|
/* Rest of includes */
|
|
|
|
#include <sys/stat.h>
|
|
#include <pwd.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
|
|
typedef char size_t_check[((__stdiosize_t) -1) > 0 ? 1 : -1];
|
|
|
|
/* Assertion */
|
|
|
|
#ifndef NDEBUG
|
|
#define ASSERT(x) (void) ((x) ? 0 : __xassert(__FILE__))
|
|
#else
|
|
#define ASSERT(x)
|
|
#endif
|
|
|
|
/* Useful macros */
|
|
|
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
|
|
|
/* Print buffer size calculation */
|
|
|
|
#define MININTBITS 3 /* least bits required --- octal */
|
|
#define MAXINTPREFIX 3 /* overhead for prefix (+0x) */
|
|
#define MAXINTINSERT 0 /* overhead for insertions */
|
|
#define MAXINTSUFFIX 0 /* overhead for suffix */
|
|
#define MAXINTDIGITS ((sizeof(long)*CHAR_BIT+MININTBITS-1) \
|
|
/MININTBITS*MININTBITS)
|
|
#define PINTBUFFER (MAXINTDIGITS+MAXINTPREFIX+MAXINTINSERT+MAXINTSUFFIX)
|
|
|
|
#ifndef NOFLOAT
|
|
# define MAXFLTPREFIX 1 /* overhead for prefix (+) */
|
|
# define MAXFLTINSERT 1 /* overhead for insertions (.) */
|
|
# define MAXFLTSUFFIX 5 /* overhead for suffix (e-308) */
|
|
# define MAXFLTDIGITS (LDBL_DIG+2)
|
|
# define PFLTBUFFER (MAXFLTDIGITS+MAXFLTPREFIX+MAXFLTINSERT+MAXFLTSUFFIX)
|
|
#else
|
|
# define PFLTBUFFER 0
|
|
#endif
|
|
|
|
#define PWRITEAHEAD 4 /* write ahead in _vfprintf */
|
|
|
|
#define PBUFFERSIZE MAX(MAX(PINTBUFFER, PFLTBUFFER),PWRITEAHEAD)
|
|
|
|
/* Formatted output conversion status bits */
|
|
|
|
#define F_LEFTJUSTIFY 0x0001 /* left justify */
|
|
#define F_SHOWSIGN 0x0002 /* display a sign */
|
|
#define F_BLANKPREFIX 0x0004 /* prefix with blank */
|
|
#define F_ALTERNATE 0x0008 /* alternate format */
|
|
#define F_SHORT 0x0010 /* argument is short */
|
|
#define F_LONG 0x0020 /* argument is long */
|
|
#define F_LONGDOUBLE 0x0040 /* argument is long double */
|
|
#define F_0X 0x0080 /* 0X instead of 0x */
|
|
#define F_FPFORMATF 0x0100 /* %f format */
|
|
#define F_FPFORMATE 0x0200 /* %e format */
|
|
#define F_FPFORMATG 0x0400 /* %g format */
|
|
#define F_FPCAPITAL 0x0800 /* %E or %G */
|
|
#define F_FPFORMAT 0x0f00 /* floating point converted */
|
|
#define F_PRECISION 0x1000 /* precision valid */
|
|
|
|
/* Formatted output vector element */
|
|
|
|
typedef struct {
|
|
int att; /* attributes */
|
|
__stdiosize_t len; /* length of vector */
|
|
char *arg; /* vector */
|
|
} FV;
|
|
|
|
#define FV_F_VECTOR 0x0000 /* length and pointer */
|
|
#define FV_F_PADDING 0x0001 /* padding only */
|
|
#define FV_F_STRING 0x0002 /* null terminated string */
|
|
|
|
#define FV_FMTPREFIX 0 /* global format prefix */
|
|
#define FV_FMTARGS 1
|
|
|
|
#define FV_FLT1SIGN 1 /* prefix */
|
|
#define FV_FLT1INT 2 /* integer digits */
|
|
#define FV_FLT1INTFILL 3 /* integer fill */
|
|
#define FV_FLT1DPFRAC 4 /* decimal point and fraction */
|
|
#define FV_FLT1FRACFILL 5 /* fractional fill */
|
|
#define FV_FLT1ARGS 6
|
|
|
|
#define FV_FLT2SIGN 1 /* prefix */
|
|
#define FV_FLT2INTDP 2 /* integer digits and decimal point */
|
|
#define FV_FLT2DPFILL 3 /* decimal point fill */
|
|
#define FV_FLT2FRAC 4 /* fractional digits */
|
|
#define FV_FLT2FRACFILL 5 /* fractional fill */
|
|
#define FV_FLT2ARGS 6
|
|
|
|
#define FV_FLT3SIGN 1 /* prefix */
|
|
#define FV_FLT3MANTISSA 2 /* mantissa */
|
|
#define FV_FLT3FRACFILL 3 /* fractional fill */
|
|
#define FV_FLT3SUFFIX 4 /* suffix */
|
|
#define FV_FLT3ARGS 5
|
|
|
|
#define FV_INTSIGN 1 /* sign or prefix */
|
|
#define FV_INTINT 2 /* integer digits */
|
|
#define FV_INTARGS 3
|
|
|
|
#define FV_ARGS MAX(FV_FLT1ARGS, MAX(FV_FLT2ARGS, \
|
|
MAX(FV_FLT3ARGS, FV_INTARGS)))
|
|
|
|
/* Internal buffer pool */
|
|
|
|
#define POOLSIZE 2 /* stdin and stdout only */
|
|
|
|
/* Stdio internal types */
|
|
|
|
typedef void (*atexit_t) P((void)); /* exit handlers */
|
|
#ifndef NOFLOAT
|
|
typedef struct { /* longdouble with guard */
|
|
longdouble number;
|
|
longdouble guard;
|
|
int exponent;
|
|
} longguard;
|
|
#endif
|
|
|
|
/* Function prototypes */
|
|
|
|
int __bffil P((FILE *)); /* fail */
|
|
int __bffls P((int, FILE *)); /* fail */
|
|
int __btfls P((FILE *)); /* succeed */
|
|
|
|
int __bwrupdate P((int, FILE *)); /* write update */
|
|
int __bwronly P((int, FILE *)); /* write only */
|
|
|
|
int __brdupdate P((FILE *)); /* read update */
|
|
int __brdonly P((FILE *)); /* read only */
|
|
|
|
__stdiosize_t __iowrite P((int, char *, __stdiosize_t)); /* repeated write */
|
|
__stdiosize_t __ioread P((int, char *, __stdiosize_t)); /* repeated read */
|
|
|
|
void __ioflush P((void)); /* flush output */
|
|
__stdiosize_t __allocbuf P((FILE *)); /* allocate buffer */
|
|
void __freebuf P((FILE *)); /* deallocate buffer */
|
|
int __fopen P((const char *, const char *, int, short *));
|
|
/* fopen assist */
|
|
FILE *__file P((FILE *, int, short));/* initialise FILE */
|
|
|
|
char *__fgetlx P((char *, __stdiosize_t, FILE *));
|
|
/* read line extended */
|
|
__stdiosize_t __rlbf P((FILE *, __stdiosize_t));
|
|
/* adjust line buffered read */
|
|
|
|
int __cvt P((__stdiosize_t *, FV *, char *, VA_LIST *, int, int));
|
|
/* output */
|
|
int __tvc P((FILE *, int, VA_LIST *, int, char *));
|
|
/* input */
|
|
|
|
char *__utoa P((char *, unsigned, int)); /* unsigned to string conversion */
|
|
|
|
int __xassert P((char *)); /* assertion failed */
|
|
|
|
#ifndef NOFLOAT
|
|
void __gpow10 P((int, longguard *));/* compute 10^x with guard */
|
|
longdouble __pow10 P((int)); /* compute 10^x without guard */
|
|
|
|
longdouble __gmul P((longguard *, longguard *));
|
|
void __ggmul P((longguard *, longguard *, longguard *));
|
|
void __gguard P((longguard *));
|
|
longdouble __gnumber P((longguard *));
|
|
void __gnormal P((longguard *));
|
|
#endif
|
|
|
|
/* Extras not in ANSI but probably could be */
|
|
|
|
int __vscanf P((const char *, VA_LIST));
|
|
int __vfscanf P((FILE *, const char *, VA_LIST));
|
|
int __vsscanf P((const char *, const char *, VA_LIST));
|
|
|
|
int __vfprintf P((FILE *, const char *, VA_LIST));
|
|
|
|
/* Library globals */
|
|
|
|
extern int errno; /* system error number */
|
|
extern int sys_nerr; /* size of error table */
|
|
extern char *sys_errlist[]; /* error descriptions */
|
|
|
|
/* Stdio internal variables */
|
|
|
|
extern void (*__Zwrapup) P((void)); /* flush stdio linkage */
|
|
extern void (*__Zatexit) P((void)); /* exit handler linkage */
|
|
extern FILE *__Zout; /* stdout linkage */
|
|
extern FILE *__Zerr; /* stderr linkage */
|
|
extern __stdiosize_t (*__Zrlbf) P((FILE *, __stdiosize_t));
|
|
/* rlbf() linkage */
|
|
extern FILE *__iop; /* stream list */
|
|
extern __stdiobuf_t *__iob[POOLSIZE]; /* buffer pool */
|
|
extern char __zfill[]; /* zero fill */
|
|
extern long __ipow10[]; /* powers of 10 */
|
|
extern int __Mipow10; /* exponent of the largest power */
|
|
|
|
#ifndef NOFLOAT
|
|
extern longdouble *__fpow10; /* floating point version */
|
|
extern char __xfptvc; /* tvc linkage for library */
|
|
extern char __xfpcvt; /* cvt linkage for library */
|
|
#endif
|
|
|
|
/* Library calls */
|
|
|
|
void *malloc P((size_t)); /* memory allocator */
|
|
void free P((void *)); /* free memory */
|
|
|
|
#ifndef NOFLOAT
|
|
longdouble LMODF P((longdouble, double *)); /* separate integer and fraction */
|
|
longdouble LFREXP P((longdouble, int *)); /* separate mantissa and exponent */
|
|
longdouble LLDEXP P((longdouble, int)); /* scale by a power of two */
|
|
#endif
|
|
|
|
/* System calls */
|
|
|
|
#ifndef OPEN3
|
|
int open P((const char *, int)); /* two argument open */
|
|
# define open __open3 /* fake three argument open */
|
|
# undef O_CREAT
|
|
# undef O_APPEND
|
|
# undef O_TRUNC
|
|
# define O_CREAT (~(O_RDONLY|O_WRONLY|O_RDWR) ^ \
|
|
(~(O_RDONLY|O_WRONLY|O_RDWR) & \
|
|
(~(O_RDONLY|O_WRONLY|O_RDWR) - 1)))
|
|
# define O_APPEND (~(O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) ^ \
|
|
(~(O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) & \
|
|
(~(O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) - 1)))
|
|
# define O_TRUNC (~(O_APPEND|O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) ^ \
|
|
(~(O_APPEND|O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) & \
|
|
(~(O_APPEND|O_CREAT|O_RDONLY|O_WRONLY|O_RDWR) - 1)))
|
|
#endif
|
|
|
|
void abort P((void)); /* abort to system */
|
|
void _exit P((int)); /* exit to system */
|
|
int isatty P((int)); /* channel is tty */
|
|
int close P((int)); /* close channel */
|
|
int creat P((const char *, MODE_T)); /* create a file */
|
|
int open P((const char *, int, ...)); /* open a file */
|
|
int dup2 P((int, int)); /* duplicate file descriptor */
|
|
off_t lseek P((int, off_t, int)); /* seek within file */
|
|
int read P((int, char *, unsigned int)); /* read channel */
|
|
int write P((int, char *, unsigned int)); /* write channel */
|
|
int unlink P((const char *)); /* unlink a file */
|
|
int link P((const char *, const char *)); /* link a file */
|
|
int stat P((const char *, struct stat *)); /* file status */
|
|
mode_t umask P((MODE_T)); /* permission mask */
|
|
int chmod P((const char *, MODE_T)); /* change permission */
|
|
pid_t getpid P((void)); /* get process id */
|
|
time_t time P((time_t *)); /* get time */
|
|
uid_t geteuid P((void)); /* get effective user id */
|
|
uid_t getuid P((void)); /* get user id */
|
|
struct passwd * getpwuid P((UID_T)); /* get passwd from uid */
|
|
signal_t signal P((int, signal_t)); /* set signals */
|
|
|
|
/* Size of tty buffers */
|
|
|
|
#define TTYBUFSIZ 81
|
|
|
|
/* Flag manipulation macros */
|
|
|
|
#define TESTFLAG(f,x) (((f)->__flag & (x)) != 0)
|
|
#define SETFLAG(f,x) ((f)->__flag |= (x))
|
|
#define CLEARFLAG(f,x) ((f)->__flag &= ~(x))
|
|
#define GETFLAG(f,x) ((f)->__flag & (x))
|
|
#define ALLFLAGS(f) ((f)->__flag)
|
|
#define TOGGLEFLAG(f,x) ((f)->__flag ^= (x))
|
|
#define SAVEFLAG(f,p) ((p) = (int) ((f)->__flag))
|
|
#define RESTOREFLAG(f,p) ((f)->__flag = (short) (p))
|
|
|
|
/* Insert stream descriptor into __iop chain
|
|
*
|
|
* The __iop list element pointed to by p is inserted into the
|
|
* __iop chain.
|
|
*/
|
|
#define FINSERT(p) ( (p)->__next=__iop, __iop=(p) )
|
|
|
|
/* Getc with full buffering
|
|
*
|
|
* This version of getc assumes that there is an input buffer
|
|
* that is not empty and simply grabs the character from there.
|
|
*/
|
|
#define FGETC(p) ( UCHAR(*(p)->__rptr++) )
|
|
|
|
/* Putc for non buffered streams
|
|
*
|
|
* This version of putc is explicitly for unbuffered streams. A
|
|
* call is made directly to the buffer flushing code.
|
|
*/
|
|
#define NPUTC(x,p) ( (*(p)->__flsbuf)((x),(p)) )
|
|
|
|
/* Putc with full buffering
|
|
*
|
|
* This version of putc() assumes that there is an output buffer
|
|
* that is not full and simply dumps the character in there.
|
|
*/
|
|
#define FPUTC(x, p) ( UCHAR((*(p)->__wptr++ = (x))) )
|
|
|
|
/* Flush a stream
|
|
*
|
|
* Call the flush routine to clear the output buffer.
|
|
*/
|
|
#define FFLUSH(f) ( (*(f)->__flush)(f) )
|
|
|
|
/* Set __flsbuf
|
|
*
|
|
* Set the __flsbuf function pointer.
|
|
*/
|
|
#define SETFLSBUF(f,p) ( (f)->__flsbuf = (p) )
|
|
|
|
/* Set __filbuf
|
|
*
|
|
* Set the __filbuf function pointer.
|
|
*/
|
|
#define SETFILBUF(f,p) ( (f)->__filbuf = (p) )
|
|
|
|
/* Set __flush
|
|
*
|
|
* Set the __flush function pointer.
|
|
*/
|
|
#define SETFLUSH(f,p) ( (f)->__flush = (p) )
|
|
|
|
/* Initialise an output buffer
|
|
*
|
|
* This macro uses __base and __bufsiz to initialise __wptr and
|
|
* __wend. __wptr will be set to point at the base of the
|
|
* buffer. __wend will be set to point at one past the end of the
|
|
* buffer if the stream is buffered otherwise it will point at
|
|
* the base of the buffer. Line buffered streams are considered to
|
|
* be fully buffered. This macro must not alter __base unless the
|
|
* code in fflush() is changed.
|
|
*/
|
|
#define INITWRITEBUFFER(f) ( \
|
|
(f)->__wend = ((f)->__wptr = (f)->__base) + \
|
|
(TESTFLAG(f, _IONBF | _IOLBF) ? 0 : (f)->__bufsiz) \
|
|
)
|
|
|
|
/* Initialise an input buffer
|
|
*
|
|
* This macro empties an input buffer. It uses __base to initialise
|
|
* __rptr and sets __rend to point to the high water mark of the buffer.
|
|
*/
|
|
#define INITREADBUFFER(f, v) ( \
|
|
(f)->__rend = ((f)->__rptr = (f)->__base) + (v) \
|
|
)
|
|
|
|
/* Flush the next write
|
|
*
|
|
* This macro initialises the buffer by setting __wend and
|
|
* __wptr to nil. This will force the next putc to call
|
|
* __flsbuf.
|
|
*/
|
|
#define CHECKNEXTWRITE(f) ( (f)->__wend = (f)->__wptr = 0 )
|
|
|
|
/* Check a write
|
|
*
|
|
* If __wptr is zero, the write buffer is checked.
|
|
*/
|
|
#define CHECKWRITE(f) ( \
|
|
(f)->__wptr == 0 ? ((f)->__wend = &(f)->__buf, (*(f)->__flsbuf)(0, f)) : 0 \
|
|
)
|
|
|
|
/* Check write status
|
|
*
|
|
* Return non-zero if a write check is scheduled, zero otherwise. This
|
|
* assumes that the stream is writeable.
|
|
*/
|
|
#define ISCHECKWRITE(f) ( (f)->__wptr == 0 )
|
|
|
|
/* Flush the next read
|
|
*
|
|
* This macro initialises the buffer by setting __rend and
|
|
* __rptr to nil. This will force the next next getc to call
|
|
* __filbuf.
|
|
*/
|
|
#define CHECKNEXTREAD(f) ( (f)->__rend = (f)->__rptr = 0 )
|
|
|
|
/* Check a read
|
|
*
|
|
* If __rptr is zero, the read buffer is checked.
|
|
*/
|
|
#define CHECKREAD(f) ( \
|
|
(f)->__rptr == 0 ? ((f)->__rend = &(f)->__buf, (*(f)->__filbuf)(f)) : 0 \
|
|
)
|
|
|
|
/* Check read status
|
|
*
|
|
* Return non-zero if a read check is scheduled, zero otherwise. This
|
|
* assumes that the stream is readable.
|
|
*/
|
|
#define ISCHECKREAD(f) ( (f)->__rptr == 0 )
|
|
|
|
/* Buffer size
|
|
*
|
|
* Return the size of the buffer. This will return rubbish
|
|
* for unbuffered streams. Line and fully buffered streams will
|
|
* have the true buffer size returned.
|
|
*/
|
|
#define BUFFERSIZE(f) ( (f)->__bufsiz )
|
|
|
|
/* Bytes left in input buffer
|
|
*
|
|
* This macro returns the number of bytes left in an input buffer.
|
|
* The result returned will be zero even in the case where the stream
|
|
* has a check scheduled.
|
|
*/
|
|
#define BYTESINREADBUFFER(f) ( (f)->__rend - (f)->__rptr )
|
|
|
|
/* Bytes written in output buffer
|
|
*
|
|
* This macro returns the number of bytes left in an output buffer.
|
|
* The result is not valid when a check has been scheduled.
|
|
*/
|
|
#define BYTESINWRITEBUFFER(f) ( (f)->__wptr - (f)->__base )
|
|
|
|
/* Unused bytes in output buffer
|
|
*
|
|
* This macro returns the number of unused bytes in an output buffer.
|
|
* Unbuffered streams will return rubbish. Line and fully buffered streams
|
|
* will have the amount of space remaining returned. In order to accommodate
|
|
* line buffered streams, __wend cannot be used. The result is not valid
|
|
* when a check has been scheduled.
|
|
*/
|
|
#define UNUSEDINWRITEBUFFER(f) ( (f)->__bufsiz - BYTESINWRITEBUFFER(f) )
|
|
|
|
/* Get pointer into write buffer
|
|
*
|
|
* This macro gets the pointer into the write buffer.
|
|
*/
|
|
#define GETWRITEPTR(f) ( (f)->__wptr )
|
|
|
|
/* Set pointer into write buffer
|
|
*
|
|
* This macro sets the pointer into the write buffer.
|
|
*/
|
|
#define SETWRITEPTR(f,p) ( (f)->__wptr = (p) )
|
|
|
|
/* Get pointer to end of write buffer
|
|
*
|
|
* This macro returns the end of write buffer pointer. This may not
|
|
* point to the real end of the write buffer.
|
|
*/
|
|
#define GETWRITEEND(f) ( (f)->__wend )
|
|
|
|
/* Get pointer to limit of write buffer
|
|
*
|
|
* This macro returns the limit of write buffer pointer. This will
|
|
* point to the real end of the write buffer.
|
|
*/
|
|
#define GETWRITELIMIT(f) ( (f)->__base + BUFFERSIZE(f) )
|
|
|
|
/* Get pointer into read buffer
|
|
*
|
|
* This macro gets the pointer into the read buffer.
|
|
*/
|
|
#define GETREADPTR(f) ( (f)->__rptr )
|
|
|
|
/* Set pointer into read buffer
|
|
*
|
|
* This macro sets the pointer into the read buffer.
|
|
*/
|
|
#define SETREADPTR(f,p) ( (f)->__rptr = (p) )
|
|
|
|
/* Get pointer to end of read buffer
|
|
*
|
|
* This macro returns the end of read buffer pointer. This may not
|
|
* point to the real end of the read buffer.
|
|
*/
|
|
#define GETREADEND(f) ( (f)->__rend )
|
|
|
|
/* Get pointer to limit of read buffer
|
|
*
|
|
* This macro returns the limit of read buffer pointer. This will
|
|
* point to the real end of the read buffer.
|
|
*/
|
|
#define GETREADLIMIT(f) ( (f)->__base + BUFFERSIZE(f) )
|
|
|
|
/* Check if buffering has been set
|
|
*
|
|
* Return true if buffering has already been set. A stream
|
|
* set for unbuffered output is considered to have had
|
|
* its buffering set.
|
|
*/
|
|
#define HASBUFFER(f) ( (f)->__base != 0 )
|
|
|
|
/* Set __wend for line buffering
|
|
*
|
|
* Set __wend for line buffering. This means that _wend is set to
|
|
* point at __base.
|
|
*/
|
|
#define SETWRITELINEBUFFERING(f) ( (f)->__wend = (f)->__base )
|
|
|
|
/* Set __wend for full buffering
|
|
*
|
|
* Set __wend to __base + __bufsiz so that the entire buffer can be
|
|
* used.
|
|
*/
|
|
#define SETWRITEFULLBUFFERING(f) ( (f)->__wend = (f)->__base + (f)->__bufsiz )
|
|
|
|
/* Unroll a loop
|
|
*
|
|
* Assume that the loop must execute at least once. The first argument
|
|
* is the name of the loop control variable. The second argument is the
|
|
* name of the loop control variable. The third argument is the expression
|
|
* to be placed in the loop body. The control variable should be unsigned,
|
|
* otherwise the right shift might propagate the sign bit. The caller must
|
|
* also provide the name of a unique label.
|
|
*/
|
|
#define UNROLL_DO(l,v,x) { \
|
|
char t = (v); \
|
|
(v) = ((v)+1) >> 1; \
|
|
if (t & 1) goto l; \
|
|
do { x; l: x; } while (--(v)); \
|
|
}
|
|
|
|
#endif
|