/* * Inferno kernel and musl each have their own versions of C string and stdlib functions */ #ifndef _PLAN9_SOURCE /* * If _PLAN9_SOURCE is not set then source files are compiled using musl POSIX compliant string functions * In this case, libc.h is an internal musl include file (completely unrelated to Plan9 libc.h) */ #include #else /* * If _PLAN9_SOURCE is set then source files are compiled to use Inferno 'k' versions of stdlib functions * - Inferno stdlib strtoxx functions do not set errno * - Inferno string functions do not have POSIX compliant const/restrict qualifiers */ #ifndef _PLAN9_LIBC_H #define _PLAN9_LIBC_H #define _STRING_H // prevent musl string.h definitions #define _STDLIB_H // prevent musl stdlib.h definitions #define nelem(x) (sizeof(x)/sizeof((x)[0])) #define offsetof(s, m) (ulong)(&(((s*)0)->m)) #define assert(x) if(x){}else _assert("x") #define intern static inline /* * mem routines */ extern void* memset(void* p, int c, size_t n); //{ for(char *r = p; n; n--, r++) *r = c; return p; } extern void* memcpy(void* p, const void* q, size_t n); extern void* memccpy(void*p, const void* q, int c, size_t n); intern void* memchr(void* p, int c, size_t n) { char *sp = p; for(c = (char)c; n > 0; n--) if(*sp++ == c) return sp-1; return 0; } intern int memcmp(const void* p, const void* q, size_t n) { uchar *s=p, *t=q; for (;n && *s==*t; s++,t++) n--; return n ? *s-*t : 0; } intern void* memmove(void*p, const void* q, size_t n) { return memcpy(p, q, n); } /* * string routines */ extern void* malloc(size_t size); extern char* strchrnul(const char *s, int c); intern char* strchr(char* s, int c) { char *r = strchrnul(s, c); return *(char *)r == (char)c ? r : 0; } intern char* strrchr(char* s, int c) { const char *p, *f = nil; while ((p = strchr(s, c))) { f = p; s = p + 1; } return (char *) f; } intern size_t strlen(char* s) { return (size_t) (strchrnul(s, 0) - s); } intern int strncmp(char* l, char* r, size_t n) { if (!n--) return 0; for (; *l && *r && n && *l == *r ; l++, r++) n--; return *l - *r; } intern int strcmp(char *p, char *q) { return strncmp(p,q, 0xFFFF); } intern char* strncpy(char* p, char* q, long n) { q = memccpy(p, q, 0, n); if (q && q 0 ? (s) >= 0 : (s) <= 0) : 0) /* * time-of-day */ typedef struct Tm Tm; struct Tm { int sec; int min; int hour; int mday; int mon; int year; int wday; int yday; char zone[4]; int tzoff; }; extern Tm* gmtime(long); extern Tm* localtime(long); extern char* asctime(Tm*); extern char* ctime(long); extern double cputime(void); extern long times(long*); extern long tm2sec(Tm*); extern vlong nsec(void); /* * clock_gettime extension */ #ifndef __DEFINED_struct_timespec) #define __DEFINED_struct_timespec struct timespec { time_t tv_sec; long tv_nsec; }; #endif int clock_gettime(int, struct timespec *); /* * one-of-a-kind */ extern void _assert(char*); extern int abs(int); extern int atexit(void(*)(void)); extern void atexitdont(void(*)(void)); extern int atnotify(int(*)(void*, char*), int); extern vlong kstrtoll(const char*, char**, int); intern int atoi(char *x) { return (int) kstrtoll(x, nil, 10); } intern long atol(char *x) { return (long) kstrtoll(x, nil, 10); } intern vlong atoll(char *x) { return kstrtoll(x, nil, 10); } extern double charstod(int(*)(void*), void*); extern char* cleanname(char*); extern int dec64(uchar*, int, char*, int); extern int enc64(char*, int, uchar*, int); extern int dec32(uchar*, int, char*, int); extern int enc32(char*, int, uchar*, int); extern int dec16(uchar*, int, char*, int); extern int enc16(char*, int, uchar*, int); extern void _Noreturn exits(char*); extern double frexp(double, int*); extern ulong getcallerpc(void*); extern char* getenv(char*); extern int getfields(char*, char**, int, int, char*); extern char* getuser(void); extern char* getwd(char*, int); extern double ipow10(int); extern double ldexp(double, int); extern double modf(double, double*); extern void perror(const char*); extern double pow10(int); extern void qsort(void*, long, long, int (*)(void*, void*)); extern double strtod(char*, char**); extern long strtol(char*, char**, int); extern ulong strtoul(char*, char**, int); extern vlong strtoll(const char*, char**, int); extern uvlong strtoull(char*, char**, int); extern void sysfatal(char*, ...); extern long time(long*); extern int tolower(int); extern int toupper(int); #include /* * synchronization */ #ifndef EMU typedef struct Proc Proc; #endif typedef struct Lock Lock; struct Lock { int val; int pid; }; extern int _tas(int*); extern void lock(Lock*); extern void unlock(Lock*); extern int canlock(Lock*); typedef struct QLock QLock; struct QLock { Lock use; /* to access Qlock structure */ Proc *head; /* next process waiting for object */ Proc *tail; /* last process waiting for object */ int locked; /* flag */ }; extern void qlock(QLock*); extern void qunlock(QLock*); extern int canqlock(QLock*); extern void _qlockinit(ulong (*)(ulong, ulong)); /* called only by the thread library */ typedef struct RWLock { Lock l; /* Lock modify lock */ QLock x; /* Mutual exclusion lock */ QLock k; /* Lock for waiting writers */ int readers; /* Count of readers in lock */ } RWLock; extern int canrlock(RWLock*); extern int canwlock(RWLock*); extern void rlock(RWLock*); extern void runlock(RWLock*); extern void wlock(RWLock*); extern void wunlock(RWLock*); /* * network dialing */ #define NETPATHLEN 40 /* * system calls * */ #define getpid kgetpid #define getwd kgetwd #define STATMAX 65535U /* max length of machine-independent stat structure */ #define DIRMAX (sizeof(Dir)+STATMAX) /* max length of Dir structure */ #define ERRMAX 128 /* max length of error string */ #define MORDER 0x0003 /* mask for bits defining order of mounting */ #define MREPL 0x0000 /* mount replaces object */ #define MBEFORE 0x0001 /* mount goes before others in union directory */ #define MAFTER 0x0002 /* mount goes after others in union directory */ #define MCREATE 0x0004 /* permit creation in mounted directory */ #define MCACHE 0x0010 /* cache some data */ #define MMASK 0x0017 /* all bits on */ #define OREAD 0 /* open for read */ #define OWRITE 1 /* write */ #define ORDWR 2 /* read and write */ #define OEXEC 3 /* execute, == read but check execute permission */ #define OTRUNC 16 /* or'ed in (except for exec), truncate file first */ #define OCEXEC 32 /* or'ed in, close on exec */ #define ORCLOSE 64 /* or'ed in, remove on close */ #define OEXCL 0x1000 /* or'ed in, exclusive use (create only) */ #define AEXIST 0 /* accessible: exists */ #define AEXEC 1 /* execute access */ #define AWRITE 2 /* write access */ #define AREAD 4 /* read access */ /* bits in Qid.type */ #define QTDIR 0x80 /* type bit for directories */ #define QTAPPEND 0x40 /* type bit for append only files */ #define QTEXCL 0x20 /* type bit for exclusive use files */ #define QTMOUNT 0x10 /* type bit for mounted channel */ #define QTAUTH 0x08 /* type bit for authentication file */ #define QTFILE 0x00 /* plain file */ /* bits in Dir.mode */ #define DMDIR 0x80000000 /* mode bit for directories */ #define DMAPPEND 0x40000000 /* mode bit for append only files */ #define DMEXCL 0x20000000 /* mode bit for exclusive use files */ #define DMMOUNT 0x10000000 /* mode bit for mounted channel */ #define DMAUTH 0x08000000 /* mode bit for authentication file */ #define DMTMP 0x04000000 /* mode bit for non-backed-up files */ #define DMREAD 0x4 /* mode bit for read permission */ #define DMWRITE 0x2 /* mode bit for write permission */ #define DMEXEC 0x1 /* mode bit for execute permission */ /* rfork */ enum { RFNAMEG = (1<<0), RFENVG = (1<<1), RFFDG = (1<<2), RFNOTEG = (1<<3), RFPROC = (1<<4), RFMEM = (1<<5), RFNOWAIT = (1<<6), RFCNAMEG = (1<<10), RFCENVG = (1<<11), RFCFDG = (1<<12), RFREND = (1<<13), RFNOMNT = (1<<14) }; typedef struct Qid { uvlong path; ulong vers; uchar type; } Qid; typedef struct Dir { /* system-modified data */ ushort type; /* server type */ uint dev; /* server subtype */ /* file data */ Qid qid; /* unique id from server */ ulong mode; /* permissions */ ulong atime; /* last read time */ ulong mtime; /* last write time */ vlong length; /* file length */ char *name; /* last element of path */ char *uid; /* owner name */ char *gid; /* group name */ char *muid; /* last modifier name */ } Dir; typedef struct Waitmsg { int pid; /* of loved one */ ulong time[3]; /* of loved one & descendants */ char *msg; } Waitmsg; #define bind _BIND #define chdir _CHDIR #define close _CLOSE #define create _CREATE #define dup _DUP #define fstat _FSTAT #define fwstat _FWSTAT #define mount _MOUNT #define open _OPEN #define pipe _PIPE #define pread _PREAD #define pwrite _PWRITE #define read _READ #define remove _REMOVE #define rfork _RFORK #define seek _SEEK #define stat _STAT #define write _WRITE #define wstat _WSTAT extern void _exits(char*); extern void abort(void); extern int bind(const char*, const char*, int); extern int chdir(const char*); extern int close(int); extern int create(const char*, int, ulong); extern int dup(int, int); extern int errstr(char*, uint); extern int rfork(int); extern int fstat(int, void*, int); extern int fwstat(int, void*, int); extern int fversion(int, int, char*, int); extern int mount(int, int, const char*, int, const char*); extern int noted(int); extern int notify(void(*)(void*, char*)); extern int open(const char*, int); extern int fd2path(int, const char*, int); extern int pipe(int*); extern long pread(int, void*, long, vlong); extern long pwrite(int, const void*, long, vlong); extern long read(int, void*, long); extern long readn(int, void*, long); extern int remove(const char*); extern void* sbrk(long); extern vlong seek(int, vlong, int); extern int segflush(void*, ulong); extern int sleep(long); extern int stat(const char*, void*, int); extern long write(int, const void*, long); extern int wstat(const char*, void*, int); extern void* rendezvous(void*, void*); extern Dir* dirstat(char*); extern Dir* dirfstat(int); extern int dirwstat(char*, Dir*); extern int dirfwstat(int, Dir*); extern long dirread(int, Dir**); extern void nulldir(Dir*); extern long dirreadall(int, Dir**); extern int getpid(void); extern int getppid(void); extern void rerrstr(char*, uint); extern char* sysname(void); extern void werrstr(char*, ...); extern char *argv0; #define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\ argv[0] && argv[0][0]=='-' && argv[0][1];\ argc--, argv++) {\ char *_args, *_argt;\ Rune _argc;\ _args = &argv[0][1];\ if(_args[0]=='-' && _args[1]==0){\ argc--; argv++; break;\ }\ _argc = 0;\ while(*_args && (_args += chartorune(&_argc, _args)))\ switch(_argc) #define ARGEND SET(_argt);USED(_argt);USED(_argc); USED(_args);}USED(argv); USED(argc); #define ARGF() (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) #define EARGF(x) (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0))) #define ARGC() _argc /* * Extensions for Inferno to basic libc.h */ #define setbinmode() #undef intern #endif #endif