mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
Today's changes.
More changes.
This commit is contained in:
parent
cb27443abf
commit
8ad517944e
73 changed files with 2865 additions and 1293 deletions
|
@ -80,6 +80,7 @@ extern int fmtfdflush(Fmt*);
|
|||
extern int fmtstrinit(Fmt*);
|
||||
extern char* fmtstrflush(Fmt*);
|
||||
extern int runefmtstrinit(Fmt*);
|
||||
extern Rune* runefmtstrflush(Fmt*);
|
||||
|
||||
extern int quotestrfmt(Fmt *f);
|
||||
extern void quotefmtinstall(void);
|
||||
|
|
876
include/lib9.h
876
include/lib9.h
|
@ -1,874 +1,2 @@
|
|||
/*
|
||||
* Lib9 is miscellany from the Plan 9 C library that doesn't
|
||||
* fit into libutf or into libfmt, but is still missing from traditional
|
||||
* Unix C libraries.
|
||||
*/
|
||||
#ifndef _LIB9_H_
|
||||
#define _LIB9_H_ 1
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _BSD_SOURCE 1
|
||||
#define _SVID_SOURCE 1
|
||||
#define _XOPEN_SOURCE 1000
|
||||
#define _XOPEN_SOURCE_EXTENDED 1
|
||||
#define _LARGEFILE64_SOURCE 1
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#define __EXTENSIONS__ 1 /* SunOS */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <setjmp.h>
|
||||
#include <stddef.h>
|
||||
#include <utf.h>
|
||||
#include <fmt.h>
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
* OS-specific crap
|
||||
*/
|
||||
#define _NEEDUCHAR 1
|
||||
#define _NEEDUSHORT 1
|
||||
#define _NEEDUINT 1
|
||||
#define _NEEDULONG 1
|
||||
|
||||
typedef long p9jmp_buf[sizeof(sigjmp_buf)/sizeof(long)];
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/types.h>
|
||||
# if defined(__USE_MISC)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__sun__)
|
||||
# include <sys/types.h>
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# if !defined(_POSIX_SOURCE)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
# include <sys/types.h>
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# define _NEEDLL 1
|
||||
#endif
|
||||
|
||||
typedef signed char schar;
|
||||
typedef unsigned int u32int;
|
||||
#ifdef _NEEDUCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#ifdef _NEEDUSHORT
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
#ifdef _NEEDUINT
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#ifdef _NEEDULONG
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long long vlong;
|
||||
typedef uvlong u64int;
|
||||
typedef uchar u8int;
|
||||
typedef ushort u16int;
|
||||
|
||||
#undef _NEEDUCHAR
|
||||
#undef _NEEDUSHORT
|
||||
#undef _NEEDUINT
|
||||
#undef _NEEDULONG
|
||||
|
||||
/*
|
||||
* Begin usual libc.h
|
||||
*/
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(s, m) (ulong)(&(((s*)0)->m))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mem routines (provided by system <string.h>)
|
||||
*
|
||||
extern void* memccpy(void*, void*, int, ulong);
|
||||
extern void* memset(void*, int, ulong);
|
||||
extern int memcmp(void*, void*, ulong);
|
||||
extern void* memcpy(void*, void*, ulong);
|
||||
extern void* memmove(void*, void*, ulong);
|
||||
extern void* memchr(void*, int, ulong);
|
||||
*/
|
||||
|
||||
/*
|
||||
* string routines (provided by system <string.h>)
|
||||
*
|
||||
extern char* strcat(char*, char*);
|
||||
extern char* strchr(char*, int);
|
||||
extern int strcmp(char*, char*);
|
||||
extern char* strcpy(char*, char*);
|
||||
*/
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
/*
|
||||
extern char* strdup(char*);
|
||||
extern char* strncat(char*, char*, long);
|
||||
extern char* strncpy(char*, char*, long);
|
||||
extern int strncmp(char*, char*, long);
|
||||
extern char* strpbrk(char*, char*);
|
||||
extern char* strrchr(char*, int);
|
||||
extern char* strtok(char*, char*);
|
||||
extern long strlen(char*);
|
||||
extern long strspn(char*, char*);
|
||||
extern long strcspn(char*, char*);
|
||||
extern char* strstr(char*, char*);
|
||||
*/
|
||||
extern int cistrncmp(char*, char*, int);
|
||||
extern int cistrcmp(char*, char*);
|
||||
extern char* cistrstr(char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
|
||||
/*
|
||||
enum
|
||||
{
|
||||
UTFmax = 3,
|
||||
Runesync = 0x80,
|
||||
Runeself = 0x80,
|
||||
Runeerror = 0x80,
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
* rune routines (provided by <utf.h>
|
||||
*
|
||||
extern int runetochar(char*, Rune*);
|
||||
extern int chartorune(Rune*, char*);
|
||||
extern int runelen(long);
|
||||
extern int runenlen(Rune*, int);
|
||||
extern int fullrune(char*, int);
|
||||
extern int utflen(char*);
|
||||
extern int utfnlen(char*, long);
|
||||
extern char* utfrune(char*, long);
|
||||
extern char* utfrrune(char*, long);
|
||||
extern char* utfutf(char*, char*);
|
||||
extern char* utfecpy(char*, char*, char*);
|
||||
|
||||
extern Rune* runestrcat(Rune*, Rune*);
|
||||
extern Rune* runestrchr(Rune*, Rune);
|
||||
extern int runestrcmp(Rune*, Rune*);
|
||||
extern Rune* runestrcpy(Rune*, Rune*);
|
||||
extern Rune* runestrncpy(Rune*, Rune*, long);
|
||||
extern Rune* runestrecpy(Rune*, Rune*, Rune*);
|
||||
extern Rune* runestrdup(Rune*);
|
||||
extern Rune* runestrncat(Rune*, Rune*, long);
|
||||
extern int runestrncmp(Rune*, Rune*, long);
|
||||
extern Rune* runestrrchr(Rune*, Rune);
|
||||
extern long runestrlen(Rune*);
|
||||
extern Rune* runestrstr(Rune*, Rune*);
|
||||
|
||||
extern Rune tolowerrune(Rune);
|
||||
extern Rune totitlerune(Rune);
|
||||
extern Rune toupperrune(Rune);
|
||||
extern int isalpharune(Rune);
|
||||
extern int islowerrune(Rune);
|
||||
extern int isspacerune(Rune);
|
||||
extern int istitlerune(Rune);
|
||||
extern int isupperrune(Rune);
|
||||
*/
|
||||
|
||||
/*
|
||||
* malloc (provied by system <stdlib.h>)
|
||||
*
|
||||
extern void* malloc(ulong);
|
||||
*/
|
||||
extern void* p9malloc(ulong);
|
||||
extern void* mallocz(ulong, int);
|
||||
/*
|
||||
extern void free(void*);
|
||||
extern ulong msize(void*);
|
||||
extern void* calloc(ulong, ulong);
|
||||
extern void* realloc(void*, ulong);
|
||||
*/
|
||||
extern void setmalloctag(void*, ulong);
|
||||
extern void setrealloctag(void*, ulong);
|
||||
extern ulong getmalloctag(void*);
|
||||
extern ulong getrealloctag(void*);
|
||||
/*
|
||||
extern void* malloctopoolblock(void*);
|
||||
*/
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define malloc p9malloc
|
||||
#endif
|
||||
|
||||
/*
|
||||
* print routines (provided by <fmt.h>)
|
||||
*
|
||||
typedef struct Fmt Fmt;
|
||||
struct Fmt{
|
||||
uchar runes;
|
||||
void *start;
|
||||
void *to;
|
||||
void *stop;
|
||||
int (*flush)(Fmt *);
|
||||
void *farg;
|
||||
int nfmt;
|
||||
va_list args;
|
||||
int r;
|
||||
int width;
|
||||
int prec;
|
||||
ulong flags;
|
||||
};
|
||||
|
||||
enum{
|
||||
FmtWidth = 1,
|
||||
FmtLeft = FmtWidth << 1,
|
||||
FmtPrec = FmtLeft << 1,
|
||||
FmtSharp = FmtPrec << 1,
|
||||
FmtSpace = FmtSharp << 1,
|
||||
FmtSign = FmtSpace << 1,
|
||||
FmtZero = FmtSign << 1,
|
||||
FmtUnsigned = FmtZero << 1,
|
||||
FmtShort = FmtUnsigned << 1,
|
||||
FmtLong = FmtShort << 1,
|
||||
FmtVLong = FmtLong << 1,
|
||||
FmtComma = FmtVLong << 1,
|
||||
FmtByte = FmtComma << 1,
|
||||
|
||||
FmtFlag = FmtByte << 1
|
||||
};
|
||||
|
||||
extern int print(char*, ...);
|
||||
extern char* seprint(char*, char*, char*, ...);
|
||||
extern char* vseprint(char*, char*, char*, va_list);
|
||||
extern int snprint(char*, int, char*, ...);
|
||||
extern int vsnprint(char*, int, char*, va_list);
|
||||
extern char* smprint(char*, ...);
|
||||
extern char* vsmprint(char*, va_list);
|
||||
extern int sprint(char*, char*, ...);
|
||||
extern int fprint(int, char*, ...);
|
||||
extern int vfprint(int, char*, va_list);
|
||||
|
||||
extern int runesprint(Rune*, char*, ...);
|
||||
extern int runesnprint(Rune*, int, char*, ...);
|
||||
extern int runevsnprint(Rune*, int, char*, va_list);
|
||||
extern Rune* runeseprint(Rune*, Rune*, char*, ...);
|
||||
extern Rune* runevseprint(Rune*, Rune*, char*, va_list);
|
||||
extern Rune* runesmprint(char*, ...);
|
||||
extern Rune* runevsmprint(char*, va_list);
|
||||
|
||||
extern int fmtfdinit(Fmt*, int, char*, int);
|
||||
extern int fmtfdflush(Fmt*);
|
||||
extern int fmtstrinit(Fmt*);
|
||||
extern char* fmtstrflush(Fmt*);
|
||||
extern int runefmtstrinit(Fmt*);
|
||||
extern Rune* runefmtstrflush(Fmt*);
|
||||
|
||||
extern int fmtinstall(int, int (*)(Fmt*));
|
||||
extern int dofmt(Fmt*, char*);
|
||||
extern int dorfmt(Fmt*, Rune*);
|
||||
extern int fmtprint(Fmt*, char*, ...);
|
||||
extern int fmtvprint(Fmt*, char*, va_list);
|
||||
extern int fmtrune(Fmt*, int);
|
||||
extern int fmtstrcpy(Fmt*, char*);
|
||||
extern int fmtrunestrcpy(Fmt*, Rune*);
|
||||
*/
|
||||
|
||||
/*
|
||||
* error string for %r
|
||||
* supplied on per os basis, not part of fmt library
|
||||
*
|
||||
* (provided by lib9, but declared in fmt.h)
|
||||
*
|
||||
extern int errfmt(Fmt *f);
|
||||
*/
|
||||
|
||||
/*
|
||||
* quoted strings
|
||||
*/
|
||||
extern char *unquotestrdup(char*);
|
||||
extern Rune *unquoterunestrdup(Rune*);
|
||||
extern char *quotestrdup(char*);
|
||||
extern Rune *quoterunestrdup(Rune*);
|
||||
/*
|
||||
* in fmt.h
|
||||
*
|
||||
extern void quotefmtinstall(void);
|
||||
extern int quotestrfmt(Fmt*);
|
||||
extern int quoterunestrfmt(Fmt*);
|
||||
*/
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define doquote fmtdoquote
|
||||
#endif
|
||||
extern int needsrcquote(int);
|
||||
|
||||
/*
|
||||
* random number (in <stdlib.h>)
|
||||
*
|
||||
extern void srand(long);
|
||||
extern int rand(void);
|
||||
*/
|
||||
extern int nrand(int);
|
||||
extern long lrand(void);
|
||||
extern long lnrand(long);
|
||||
extern double frand(void);
|
||||
extern ulong truerand(void); /* uses /dev/random */
|
||||
extern ulong ntruerand(ulong); /* uses /dev/random */
|
||||
|
||||
/*
|
||||
* math
|
||||
*/
|
||||
extern ulong getfcr(void);
|
||||
extern void setfsr(ulong);
|
||||
extern ulong getfsr(void);
|
||||
extern void setfcr(ulong);
|
||||
extern double NaN(void);
|
||||
extern double Inf(int);
|
||||
extern int isNaN(double);
|
||||
extern int isInf(double, int);
|
||||
extern ulong umuldiv(ulong, ulong, ulong);
|
||||
extern long muldiv(long, long, long);
|
||||
|
||||
/*
|
||||
* provided by math.h
|
||||
*
|
||||
extern double pow(double, double);
|
||||
extern double atan2(double, double);
|
||||
extern double fabs(double);
|
||||
extern double atan(double);
|
||||
extern double log(double);
|
||||
extern double log10(double);
|
||||
extern double exp(double);
|
||||
extern double floor(double);
|
||||
extern double ceil(double);
|
||||
extern double hypot(double, double);
|
||||
extern double sin(double);
|
||||
extern double cos(double);
|
||||
extern double tan(double);
|
||||
extern double asin(double);
|
||||
extern double acos(double);
|
||||
extern double sinh(double);
|
||||
extern double cosh(double);
|
||||
extern double tanh(double);
|
||||
extern double sqrt(double);
|
||||
extern double fmod(double, double);
|
||||
#define HUGE 3.4028234e38
|
||||
#define PIO2 1.570796326794896619231e0
|
||||
#define PI (PIO2+PIO2)
|
||||
*/
|
||||
#define PI M_PI
|
||||
#define PIO2 M_PI_2
|
||||
|
||||
/*
|
||||
* Time-of-day
|
||||
*/
|
||||
|
||||
typedef
|
||||
struct Tm
|
||||
{
|
||||
int sec;
|
||||
int min;
|
||||
int hour;
|
||||
int mday;
|
||||
int mon;
|
||||
int year;
|
||||
int wday;
|
||||
int yday;
|
||||
char zone[4];
|
||||
int tzoff;
|
||||
} Tm;
|
||||
|
||||
extern Tm* p9gmtime(long);
|
||||
extern Tm* p9localtime(long);
|
||||
extern char* p9asctime(Tm*);
|
||||
extern char* p9ctime(long);
|
||||
extern double p9cputime(void);
|
||||
extern long p9times(long*);
|
||||
extern long p9tm2sec(Tm*);
|
||||
extern vlong p9nsec(void);
|
||||
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define gmtime p9gmtime
|
||||
#define localtime p9localtime
|
||||
#define asctime p9asctime
|
||||
#define ctime p9ctime
|
||||
#define cputime p9cputime
|
||||
#define times p9times
|
||||
#define tm2sec p9tm2sec
|
||||
#define nsec p9nsec
|
||||
#endif
|
||||
|
||||
/*
|
||||
* one-of-a-kind
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PNPROC = 1,
|
||||
PNGROUP = 2,
|
||||
};
|
||||
|
||||
/* extern int abs(int); <stdlib.h> */
|
||||
extern int p9atexit(void(*)(void));
|
||||
extern void p9atexitdont(void(*)(void));
|
||||
extern int atnotify(int(*)(void*, char*), int);
|
||||
/*
|
||||
* <stdlib.h>
|
||||
extern double atof(char*); <stdlib.h>
|
||||
extern int atoi(char*);
|
||||
extern long atol(char*);
|
||||
*/
|
||||
extern vlong atoll(const char*);
|
||||
extern double charstod(int(*)(void*), void*);
|
||||
extern char* cleanname(char*);
|
||||
extern int p9decrypt(void*, void*, int);
|
||||
extern int p9encrypt(void*, void*, int);
|
||||
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 int encodefmt(Fmt*);
|
||||
extern int dirmodefmt(Fmt*);
|
||||
extern void exits(char*);
|
||||
extern double frexp(double, int*);
|
||||
extern ulong getcallerpc(void*);
|
||||
extern char* p9getenv(char*);
|
||||
extern int p9putenv(char*, char*);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
extern int gettokens(char *, char **, int, char *);
|
||||
extern char* getuser(void);
|
||||
extern char* p9getwd(char*, int);
|
||||
extern int iounit(int);
|
||||
/* extern long labs(long); <math.h> */
|
||||
/* extern double ldexp(double, int); <math.h> */
|
||||
extern void p9longjmp(p9jmp_buf, int);
|
||||
extern char* mktemp(char*);
|
||||
extern int opentemp(char*);
|
||||
/* extern double modf(double, double*); <math.h> */
|
||||
extern int netcrypt(void*, void*);
|
||||
extern void p9notejmp(void*, p9jmp_buf, int);
|
||||
extern void perror(const char*);
|
||||
extern int postnote(int, int, char *);
|
||||
extern double pow10(int);
|
||||
/* extern int putenv(char*, char*); <stdlib.h. */
|
||||
/* extern void qsort(void*, long, long, int (*)(void*, void*)); <stdlib.h> */
|
||||
/* extern int p9setjmp(p9jmp_buf); */
|
||||
#define p9setjmp(b) sigsetjmp((void*)(b), 1)
|
||||
/*
|
||||
* <stdlib.h>
|
||||
extern double strtod(char*, char**);
|
||||
extern long strtol(char*, char**, int);
|
||||
extern ulong strtoul(char*, char**, int);
|
||||
extern vlong strtoll(char*, char**, int);
|
||||
extern uvlong strtoull(char*, char**, int);
|
||||
*/
|
||||
extern void sysfatal(char*, ...);
|
||||
extern void p9syslog(int, char*, char*, ...);
|
||||
extern long time(long*);
|
||||
/* extern int tolower(int); <ctype.h> */
|
||||
/* extern int toupper(int); <ctype.h> */
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define atexit p9atexit
|
||||
#define atexitdont p9atexitdont
|
||||
#define encrypt p9encrypt
|
||||
#define decrypt p9decrypt
|
||||
#define getenv p9getenv
|
||||
#define getwd p9getwd
|
||||
#define longjmp p9longjmp
|
||||
#undef setjmp
|
||||
#define setjmp p9setjmp
|
||||
#define putenv p9putenv
|
||||
#define notejmp p9notejmp
|
||||
#define jmp_buf p9jmp_buf
|
||||
#define syslog p9syslog
|
||||
#endif
|
||||
|
||||
/*
|
||||
* synchronization
|
||||
*/
|
||||
typedef
|
||||
struct Lock {
|
||||
int val;
|
||||
} Lock;
|
||||
|
||||
extern int _tas(int*);
|
||||
|
||||
extern void lock(Lock*);
|
||||
extern void unlock(Lock*);
|
||||
extern int canlock(Lock*);
|
||||
|
||||
typedef struct QLp QLp;
|
||||
struct QLp
|
||||
{
|
||||
int inuse;
|
||||
QLp *next;
|
||||
char state;
|
||||
};
|
||||
|
||||
typedef
|
||||
struct QLock
|
||||
{
|
||||
Lock lock;
|
||||
int locked;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
} QLock;
|
||||
|
||||
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 lock;
|
||||
int readers; /* number of readers */
|
||||
int writer; /* number of writers */
|
||||
QLp *head; /* list of waiting processes */
|
||||
QLp *tail;
|
||||
} RWLock;
|
||||
|
||||
extern void rlock(RWLock*);
|
||||
extern void runlock(RWLock*);
|
||||
extern int canrlock(RWLock*);
|
||||
extern void wlock(RWLock*);
|
||||
extern void wunlock(RWLock*);
|
||||
extern int canwlock(RWLock*);
|
||||
|
||||
typedef
|
||||
struct Rendez
|
||||
{
|
||||
QLock *l;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
} Rendez;
|
||||
|
||||
extern void rsleep(Rendez*); /* unlocks r->l, sleeps, locks r->l again */
|
||||
extern int rwakeup(Rendez*);
|
||||
extern int rwakeupall(Rendez*);
|
||||
extern void** privalloc(void);
|
||||
extern void privfree(void**);
|
||||
|
||||
/*
|
||||
* network dialing
|
||||
*/
|
||||
#define NETPATHLEN 40
|
||||
extern int p9accept(int, char*);
|
||||
extern int p9announce(char*, char*);
|
||||
extern int p9dial(char*, char*, char*, int*);
|
||||
extern void p9setnetmtpt(char*, int, char*);
|
||||
extern int p9hangup(int);
|
||||
extern int p9listen(char*, char*);
|
||||
extern char* p9netmkaddr(char*, char*, char*);
|
||||
extern int p9reject(int, char*, char*);
|
||||
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define accept p9accept
|
||||
#define announce p9announce
|
||||
#define dial p9dial
|
||||
#define setnetmtpt p9setnetmtpt
|
||||
#define hangup p9hangup
|
||||
#define listen p9listen
|
||||
#define netmkaddr p9netmkaddr
|
||||
#define reject p9reject
|
||||
#endif
|
||||
|
||||
/*
|
||||
* encryption
|
||||
*/
|
||||
extern int pushssl(int, char*, char*, char*, int*);
|
||||
extern int pushtls(int, char*, char*, int, char*, char*);
|
||||
|
||||
/*
|
||||
* network services
|
||||
*/
|
||||
typedef struct NetConnInfo NetConnInfo;
|
||||
struct NetConnInfo
|
||||
{
|
||||
char *dir; /* connection directory */
|
||||
char *root; /* network root */
|
||||
char *spec; /* binding spec */
|
||||
char *lsys; /* local system */
|
||||
char *lserv; /* local service */
|
||||
char *rsys; /* remote system */
|
||||
char *rserv; /* remote service */
|
||||
};
|
||||
extern NetConnInfo* getnetconninfo(char*, int);
|
||||
extern void freenetconninfo(NetConnInfo*);
|
||||
|
||||
/*
|
||||
* system calls
|
||||
*
|
||||
*/
|
||||
#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 */
|
||||
|
||||
/* Segattch */
|
||||
#define SG_RONLY 0040 /* read only */
|
||||
#define SG_CEXEC 0100 /* detach on exec */
|
||||
|
||||
#define NCONT 0 /* continue after note */
|
||||
#define NDFLT 1 /* terminate after note */
|
||||
#define NSAVE 2 /* clear note but hold state */
|
||||
#define NRSTR 3 /* restore saved state */
|
||||
|
||||
/* 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 DMREAD 0x4 /* mode bit for read permission */
|
||||
#define DMWRITE 0x2 /* mode bit for write permission */
|
||||
#define DMEXEC 0x1 /* mode bit for execute permission */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef RFFDG
|
||||
#undef RFNOTEG
|
||||
#undef RFPROC
|
||||
#undef RFMEM
|
||||
#undef RFNOWAIT
|
||||
#undef RFCFDG
|
||||
#undef RFNAMEG
|
||||
#undef RFENVG
|
||||
#undef RFCENVG
|
||||
#undef RFCFDG
|
||||
#undef RFCNAMEG
|
||||
#endif
|
||||
|
||||
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) */
|
||||
};
|
||||
|
||||
extern int ffork(int, void(*)(void*), void*);
|
||||
|
||||
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;
|
||||
|
||||
/* keep /sys/src/ape/lib/ap/plan9/sys9.h in sync with this -rsc */
|
||||
typedef
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
} Waitmsg;
|
||||
|
||||
typedef
|
||||
struct IOchunk
|
||||
{
|
||||
void *addr;
|
||||
ulong len;
|
||||
} IOchunk;
|
||||
|
||||
extern void _exits(char*);
|
||||
|
||||
extern void abort(void);
|
||||
extern int p9access(char*, int);
|
||||
extern long p9alarm(ulong);
|
||||
extern int await(char*, int);
|
||||
extern int awaitnohang(char*, int);
|
||||
/* extern int bind(char*, char*, int); give up */
|
||||
/* extern int brk(void*); <unistd.h> */
|
||||
extern int p9chdir(char*);
|
||||
extern int close(int);
|
||||
extern int p9create(char*, int, ulong);
|
||||
extern int p9dup(int, int);
|
||||
extern int errstr(char*, uint);
|
||||
extern int p9exec(char*, char*[]);
|
||||
/* extern int execl(char*, ...); <unistd.h> */
|
||||
/* extern int fork(void); <unistd.h> */
|
||||
extern int p9rfork(int);
|
||||
/* not implemented
|
||||
extern int fauth(int, char*);
|
||||
extern int fstat(int, uchar*, int);
|
||||
extern int fwstat(int, uchar*, int);
|
||||
extern int fversion(int, int, char*, int);
|
||||
extern int mount(int, int, char*, int, char*);
|
||||
extern int unmount(char*, char*);
|
||||
*/
|
||||
extern int noted(int);
|
||||
extern int notify(void(*)(void*, char*));
|
||||
extern int p9open(char*, int);
|
||||
extern int fd2path(int, char*, int);
|
||||
extern int p9pipe(int*);
|
||||
/*
|
||||
* use defs from <unistd.h>
|
||||
extern long pread(int, void*, long, vlong);
|
||||
extern long preadv(int, IOchunk*, int, vlong);
|
||||
extern long pwrite(int, void*, long, vlong);
|
||||
extern long pwritev(int, IOchunk*, int, vlong);
|
||||
extern long read(int, void*, long);
|
||||
*/
|
||||
extern long readn(int, void*, long);
|
||||
/* extern long readv(int, IOchunk*, int); <unistd.h> */
|
||||
extern int remove(const char*);
|
||||
/* extern void* sbrk(ulong); <unistd.h> */
|
||||
/* extern long oseek(int, long, int); */
|
||||
extern vlong p9seek(int, vlong, int);
|
||||
/* give up
|
||||
extern long segattach(int, char*, void*, ulong);
|
||||
extern int segbrk(void*, void*);
|
||||
extern int segdetach(void*);
|
||||
extern int segflush(void*, ulong);
|
||||
extern int segfree(void*, ulong);
|
||||
*/
|
||||
extern int p9sleep(long);
|
||||
/* extern int stat(char*, uchar*, int); give up */
|
||||
extern Waitmsg* p9wait(void);
|
||||
extern Waitmsg* waitnohang(void);
|
||||
extern int p9waitpid(void);
|
||||
/* <unistd.h>
|
||||
extern long write(int, void*, long);
|
||||
extern long writev(int, IOchunk*, int);
|
||||
*/
|
||||
/* extern int wstat(char*, uchar*, int); give up */
|
||||
extern ulong rendezvous(ulong, ulong);
|
||||
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define alarm p9alarm
|
||||
#define dup p9dup
|
||||
#define exec p9exec
|
||||
#define seek p9seek
|
||||
#define sleep p9sleep
|
||||
#define wait p9wait
|
||||
#define waitpid p9waitpid
|
||||
#define rfork p9rfork
|
||||
#define access p9access
|
||||
#define create p9create
|
||||
#define open p9open
|
||||
#define pipe p9pipe
|
||||
#endif
|
||||
|
||||
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); <unistd.h> */
|
||||
/* extern int getppid(void); */
|
||||
extern void rerrstr(char*, uint);
|
||||
extern char* sysname(void);
|
||||
extern void werrstr(char*, ...);
|
||||
extern char* getns(void);
|
||||
extern int sendfd(int, int);
|
||||
extern int recvfd(int);
|
||||
extern int post9pservice(int, char*);
|
||||
|
||||
/* external names that we don't want to step on */
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define main p9main
|
||||
#endif
|
||||
|
||||
/* compiler directives on plan 9 */
|
||||
#define USED(x) if(x){}else{}
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
/* command line */
|
||||
extern char *argv0;
|
||||
extern void __fixargv0(void);
|
||||
#define ARGBEGIN for((argv0?0:(argv0=(__fixargv0(),*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
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* _LIB9_H_ */
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
|
|
@ -43,4 +43,4 @@ typedef struct Sinstack Sinstack;
|
|||
extern char *s_rdinstack(Sinstack*, String*);
|
||||
extern Sinstack *s_allocinstack(char*);
|
||||
extern void s_freeinstack(Sinstack*);
|
||||
#endif BGETC
|
||||
#endif /* BGETC */
|
||||
|
|
794
include/libc.h
794
include/libc.h
|
@ -1,2 +1,794 @@
|
|||
#include <lib9.h>
|
||||
/*
|
||||
* Lib9 is miscellany from the Plan 9 C library that doesn't
|
||||
* fit into libutf or into libfmt, but is still missing from traditional
|
||||
* Unix C libraries.
|
||||
*/
|
||||
#ifndef _LIBC_H_
|
||||
#define _LIBC_H_ 1
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Begin usual libc.h
|
||||
*/
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(s, m) (ulong)(&(((s*)0)->m))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mem routines (provided by system <string.h>)
|
||||
*
|
||||
extern void* memccpy(void*, void*, int, ulong);
|
||||
extern void* memset(void*, int, ulong);
|
||||
extern int memcmp(void*, void*, ulong);
|
||||
extern void* memcpy(void*, void*, ulong);
|
||||
extern void* memmove(void*, void*, ulong);
|
||||
extern void* memchr(void*, int, ulong);
|
||||
*/
|
||||
|
||||
/*
|
||||
* string routines (provided by system <string.h>)
|
||||
*
|
||||
extern char* strcat(char*, char*);
|
||||
extern char* strchr(char*, int);
|
||||
extern int strcmp(char*, char*);
|
||||
extern char* strcpy(char*, char*);
|
||||
*/
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
/*
|
||||
extern char* strdup(char*);
|
||||
extern char* strncat(char*, char*, long);
|
||||
extern char* strncpy(char*, char*, long);
|
||||
extern int strncmp(char*, char*, long);
|
||||
extern char* strpbrk(char*, char*);
|
||||
extern char* strrchr(char*, int);
|
||||
extern char* strtok(char*, char*);
|
||||
extern long strlen(char*);
|
||||
extern long strspn(char*, char*);
|
||||
extern long strcspn(char*, char*);
|
||||
extern char* strstr(char*, char*);
|
||||
*/
|
||||
extern int cistrncmp(char*, char*, int);
|
||||
extern int cistrcmp(char*, char*);
|
||||
extern char* cistrstr(char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
|
||||
/*
|
||||
enum
|
||||
{
|
||||
UTFmax = 3,
|
||||
Runesync = 0x80,
|
||||
Runeself = 0x80,
|
||||
Runeerror = 0x80,
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
* rune routines (provided by <utf.h>
|
||||
*
|
||||
extern int runetochar(char*, Rune*);
|
||||
extern int chartorune(Rune*, char*);
|
||||
extern int runelen(long);
|
||||
extern int runenlen(Rune*, int);
|
||||
extern int fullrune(char*, int);
|
||||
extern int utflen(char*);
|
||||
extern int utfnlen(char*, long);
|
||||
extern char* utfrune(char*, long);
|
||||
extern char* utfrrune(char*, long);
|
||||
extern char* utfutf(char*, char*);
|
||||
extern char* utfecpy(char*, char*, char*);
|
||||
|
||||
extern Rune* runestrcat(Rune*, Rune*);
|
||||
extern Rune* runestrchr(Rune*, Rune);
|
||||
extern int runestrcmp(Rune*, Rune*);
|
||||
extern Rune* runestrcpy(Rune*, Rune*);
|
||||
extern Rune* runestrncpy(Rune*, Rune*, long);
|
||||
extern Rune* runestrecpy(Rune*, Rune*, Rune*);
|
||||
extern Rune* runestrdup(Rune*);
|
||||
extern Rune* runestrncat(Rune*, Rune*, long);
|
||||
extern int runestrncmp(Rune*, Rune*, long);
|
||||
extern Rune* runestrrchr(Rune*, Rune);
|
||||
extern long runestrlen(Rune*);
|
||||
extern Rune* runestrstr(Rune*, Rune*);
|
||||
|
||||
extern Rune tolowerrune(Rune);
|
||||
extern Rune totitlerune(Rune);
|
||||
extern Rune toupperrune(Rune);
|
||||
extern int isalpharune(Rune);
|
||||
extern int islowerrune(Rune);
|
||||
extern int isspacerune(Rune);
|
||||
extern int istitlerune(Rune);
|
||||
extern int isupperrune(Rune);
|
||||
*/
|
||||
|
||||
/*
|
||||
* malloc (provied by system <stdlib.h>)
|
||||
*
|
||||
extern void* malloc(ulong);
|
||||
*/
|
||||
extern void* p9malloc(ulong);
|
||||
extern void* mallocz(ulong, int);
|
||||
/*
|
||||
extern void free(void*);
|
||||
extern ulong msize(void*);
|
||||
extern void* calloc(ulong, ulong);
|
||||
extern void* realloc(void*, ulong);
|
||||
*/
|
||||
extern void setmalloctag(void*, ulong);
|
||||
extern void setrealloctag(void*, ulong);
|
||||
extern ulong getmalloctag(void*);
|
||||
extern ulong getrealloctag(void*);
|
||||
/*
|
||||
extern void* malloctopoolblock(void*);
|
||||
*/
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define malloc p9malloc
|
||||
#endif
|
||||
|
||||
/*
|
||||
* print routines (provided by <fmt.h>)
|
||||
*
|
||||
typedef struct Fmt Fmt;
|
||||
struct Fmt{
|
||||
uchar runes;
|
||||
void *start;
|
||||
void *to;
|
||||
void *stop;
|
||||
int (*flush)(Fmt *);
|
||||
void *farg;
|
||||
int nfmt;
|
||||
va_list args;
|
||||
int r;
|
||||
int width;
|
||||
int prec;
|
||||
ulong flags;
|
||||
};
|
||||
|
||||
enum{
|
||||
FmtWidth = 1,
|
||||
FmtLeft = FmtWidth << 1,
|
||||
FmtPrec = FmtLeft << 1,
|
||||
FmtSharp = FmtPrec << 1,
|
||||
FmtSpace = FmtSharp << 1,
|
||||
FmtSign = FmtSpace << 1,
|
||||
FmtZero = FmtSign << 1,
|
||||
FmtUnsigned = FmtZero << 1,
|
||||
FmtShort = FmtUnsigned << 1,
|
||||
FmtLong = FmtShort << 1,
|
||||
FmtVLong = FmtLong << 1,
|
||||
FmtComma = FmtVLong << 1,
|
||||
FmtByte = FmtComma << 1,
|
||||
|
||||
FmtFlag = FmtByte << 1
|
||||
};
|
||||
|
||||
extern int print(char*, ...);
|
||||
extern char* seprint(char*, char*, char*, ...);
|
||||
extern char* vseprint(char*, char*, char*, va_list);
|
||||
extern int snprint(char*, int, char*, ...);
|
||||
extern int vsnprint(char*, int, char*, va_list);
|
||||
extern char* smprint(char*, ...);
|
||||
extern char* vsmprint(char*, va_list);
|
||||
extern int sprint(char*, char*, ...);
|
||||
extern int fprint(int, char*, ...);
|
||||
extern int vfprint(int, char*, va_list);
|
||||
|
||||
extern int runesprint(Rune*, char*, ...);
|
||||
extern int runesnprint(Rune*, int, char*, ...);
|
||||
extern int runevsnprint(Rune*, int, char*, va_list);
|
||||
extern Rune* runeseprint(Rune*, Rune*, char*, ...);
|
||||
extern Rune* runevseprint(Rune*, Rune*, char*, va_list);
|
||||
extern Rune* runesmprint(char*, ...);
|
||||
extern Rune* runevsmprint(char*, va_list);
|
||||
|
||||
extern int fmtfdinit(Fmt*, int, char*, int);
|
||||
extern int fmtfdflush(Fmt*);
|
||||
extern int fmtstrinit(Fmt*);
|
||||
extern char* fmtstrflush(Fmt*);
|
||||
extern int runefmtstrinit(Fmt*);
|
||||
extern Rune* runefmtstrflush(Fmt*);
|
||||
|
||||
extern int fmtinstall(int, int (*)(Fmt*));
|
||||
extern int dofmt(Fmt*, char*);
|
||||
extern int dorfmt(Fmt*, Rune*);
|
||||
extern int fmtprint(Fmt*, char*, ...);
|
||||
extern int fmtvprint(Fmt*, char*, va_list);
|
||||
extern int fmtrune(Fmt*, int);
|
||||
extern int fmtstrcpy(Fmt*, char*);
|
||||
extern int fmtrunestrcpy(Fmt*, Rune*);
|
||||
*/
|
||||
|
||||
/*
|
||||
* error string for %r
|
||||
* supplied on per os basis, not part of fmt library
|
||||
*
|
||||
* (provided by lib9, but declared in fmt.h)
|
||||
*
|
||||
extern int errfmt(Fmt *f);
|
||||
*/
|
||||
|
||||
/*
|
||||
* quoted strings
|
||||
*/
|
||||
extern char *unquotestrdup(char*);
|
||||
extern Rune *unquoterunestrdup(Rune*);
|
||||
extern char *quotestrdup(char*);
|
||||
extern Rune *quoterunestrdup(Rune*);
|
||||
/*
|
||||
* in fmt.h
|
||||
*
|
||||
extern void quotefmtinstall(void);
|
||||
extern int quotestrfmt(Fmt*);
|
||||
extern int quoterunestrfmt(Fmt*);
|
||||
*/
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define doquote fmtdoquote
|
||||
#endif
|
||||
extern int needsrcquote(int);
|
||||
|
||||
/*
|
||||
* random number (in <stdlib.h>)
|
||||
*
|
||||
extern void srand(long);
|
||||
extern int rand(void);
|
||||
*/
|
||||
extern int nrand(int);
|
||||
extern long lrand(void);
|
||||
extern long lnrand(long);
|
||||
extern double frand(void);
|
||||
extern ulong truerand(void); /* uses /dev/random */
|
||||
extern ulong ntruerand(ulong); /* uses /dev/random */
|
||||
|
||||
/*
|
||||
* math
|
||||
*/
|
||||
extern ulong getfcr(void);
|
||||
extern void setfsr(ulong);
|
||||
extern ulong getfsr(void);
|
||||
extern void setfcr(ulong);
|
||||
extern double NaN(void);
|
||||
extern double Inf(int);
|
||||
extern int isNaN(double);
|
||||
extern int isInf(double, int);
|
||||
extern ulong umuldiv(ulong, ulong, ulong);
|
||||
extern long muldiv(long, long, long);
|
||||
|
||||
/*
|
||||
* provided by math.h
|
||||
*
|
||||
extern double pow(double, double);
|
||||
extern double atan2(double, double);
|
||||
extern double fabs(double);
|
||||
extern double atan(double);
|
||||
extern double log(double);
|
||||
extern double log10(double);
|
||||
extern double exp(double);
|
||||
extern double floor(double);
|
||||
extern double ceil(double);
|
||||
extern double hypot(double, double);
|
||||
extern double sin(double);
|
||||
extern double cos(double);
|
||||
extern double tan(double);
|
||||
extern double asin(double);
|
||||
extern double acos(double);
|
||||
extern double sinh(double);
|
||||
extern double cosh(double);
|
||||
extern double tanh(double);
|
||||
extern double sqrt(double);
|
||||
extern double fmod(double, double);
|
||||
#define HUGE 3.4028234e38
|
||||
#define PIO2 1.570796326794896619231e0
|
||||
#define PI (PIO2+PIO2)
|
||||
*/
|
||||
#define PI M_PI
|
||||
#define PIO2 M_PI_2
|
||||
|
||||
/*
|
||||
* Time-of-day
|
||||
*/
|
||||
|
||||
typedef
|
||||
struct Tm
|
||||
{
|
||||
int sec;
|
||||
int min;
|
||||
int hour;
|
||||
int mday;
|
||||
int mon;
|
||||
int year;
|
||||
int wday;
|
||||
int yday;
|
||||
char zone[4];
|
||||
int tzoff;
|
||||
} Tm;
|
||||
|
||||
extern Tm* p9gmtime(long);
|
||||
extern Tm* p9localtime(long);
|
||||
extern char* p9asctime(Tm*);
|
||||
extern char* p9ctime(long);
|
||||
extern double p9cputime(void);
|
||||
extern long p9times(long*);
|
||||
extern long p9tm2sec(Tm*);
|
||||
extern vlong p9nsec(void);
|
||||
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define gmtime p9gmtime
|
||||
#define localtime p9localtime
|
||||
#define asctime p9asctime
|
||||
#define ctime p9ctime
|
||||
#define cputime p9cputime
|
||||
#define times p9times
|
||||
#define tm2sec p9tm2sec
|
||||
#define nsec p9nsec
|
||||
#endif
|
||||
|
||||
/*
|
||||
* one-of-a-kind
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PNPROC = 1,
|
||||
PNGROUP = 2,
|
||||
};
|
||||
|
||||
/* extern int abs(int); <stdlib.h> */
|
||||
extern int p9atexit(void(*)(void));
|
||||
extern void p9atexitdont(void(*)(void));
|
||||
extern int atnotify(int(*)(void*, char*), int);
|
||||
/*
|
||||
* <stdlib.h>
|
||||
extern double atof(char*); <stdlib.h>
|
||||
extern int atoi(char*);
|
||||
extern long atol(char*);
|
||||
*/
|
||||
extern vlong atoll(const char*);
|
||||
extern double charstod(int(*)(void*), void*);
|
||||
extern char* cleanname(char*);
|
||||
extern int p9decrypt(void*, void*, int);
|
||||
extern int p9encrypt(void*, void*, int);
|
||||
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 int encodefmt(Fmt*);
|
||||
extern int dirmodefmt(Fmt*);
|
||||
extern void exits(char*);
|
||||
extern double frexp(double, int*);
|
||||
extern ulong getcallerpc(void*);
|
||||
extern char* p9getenv(char*);
|
||||
extern int p9putenv(char*, char*);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
extern int gettokens(char *, char **, int, char *);
|
||||
extern char* getuser(void);
|
||||
extern char* p9getwd(char*, int);
|
||||
extern int iounit(int);
|
||||
/* extern long labs(long); <math.h> */
|
||||
/* extern double ldexp(double, int); <math.h> */
|
||||
extern void p9longjmp(p9jmp_buf, int);
|
||||
extern char* mktemp(char*);
|
||||
extern int opentemp(char*);
|
||||
/* extern double modf(double, double*); <math.h> */
|
||||
extern int netcrypt(void*, void*);
|
||||
extern void p9notejmp(void*, p9jmp_buf, int);
|
||||
extern void perror(const char*);
|
||||
extern int postnote(int, int, char *);
|
||||
extern double pow10(int);
|
||||
/* extern int putenv(char*, char*); <stdlib.h. */
|
||||
/* extern void qsort(void*, long, long, int (*)(void*, void*)); <stdlib.h> */
|
||||
/* extern int p9setjmp(p9jmp_buf); */
|
||||
#define p9setjmp(b) sigsetjmp((void*)(b), 1)
|
||||
/*
|
||||
* <stdlib.h>
|
||||
extern double strtod(char*, char**);
|
||||
extern long strtol(char*, char**, int);
|
||||
extern ulong strtoul(char*, char**, int);
|
||||
extern vlong strtoll(char*, char**, int);
|
||||
extern uvlong strtoull(char*, char**, int);
|
||||
*/
|
||||
extern void sysfatal(char*, ...);
|
||||
extern void p9syslog(int, char*, char*, ...);
|
||||
extern long p9time(long*);
|
||||
/* extern int tolower(int); <ctype.h> */
|
||||
/* extern int toupper(int); <ctype.h> */
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define atexit p9atexit
|
||||
#define atexitdont p9atexitdont
|
||||
#define encrypt p9encrypt
|
||||
#define decrypt p9decrypt
|
||||
#define getenv p9getenv
|
||||
#define getwd p9getwd
|
||||
#define longjmp p9longjmp
|
||||
#undef setjmp
|
||||
#define setjmp p9setjmp
|
||||
#define putenv p9putenv
|
||||
#define notejmp p9notejmp
|
||||
#define jmp_buf p9jmp_buf
|
||||
#define syslog p9syslog
|
||||
#define time p9time
|
||||
#endif
|
||||
|
||||
/*
|
||||
* synchronization
|
||||
*/
|
||||
typedef
|
||||
struct Lock {
|
||||
int val;
|
||||
} Lock;
|
||||
|
||||
extern int _tas(int*);
|
||||
|
||||
extern void lock(Lock*);
|
||||
extern void unlock(Lock*);
|
||||
extern int canlock(Lock*);
|
||||
|
||||
typedef struct QLp QLp;
|
||||
struct QLp
|
||||
{
|
||||
int inuse;
|
||||
QLp *next;
|
||||
char state;
|
||||
};
|
||||
|
||||
typedef
|
||||
struct QLock
|
||||
{
|
||||
Lock lock;
|
||||
int locked;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
} QLock;
|
||||
|
||||
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 lock;
|
||||
int readers; /* number of readers */
|
||||
int writer; /* number of writers */
|
||||
QLp *head; /* list of waiting processes */
|
||||
QLp *tail;
|
||||
} RWLock;
|
||||
|
||||
extern void rlock(RWLock*);
|
||||
extern void runlock(RWLock*);
|
||||
extern int canrlock(RWLock*);
|
||||
extern void wlock(RWLock*);
|
||||
extern void wunlock(RWLock*);
|
||||
extern int canwlock(RWLock*);
|
||||
|
||||
typedef
|
||||
struct Rendez
|
||||
{
|
||||
QLock *l;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
} Rendez;
|
||||
|
||||
extern void rsleep(Rendez*); /* unlocks r->l, sleeps, locks r->l again */
|
||||
extern int rwakeup(Rendez*);
|
||||
extern int rwakeupall(Rendez*);
|
||||
extern void** privalloc(void);
|
||||
extern void privfree(void**);
|
||||
|
||||
/*
|
||||
* network dialing
|
||||
*/
|
||||
#define NETPATHLEN 40
|
||||
extern int p9accept(int, char*);
|
||||
extern int p9announce(char*, char*);
|
||||
extern int p9dial(char*, char*, char*, int*);
|
||||
extern void p9setnetmtpt(char*, int, char*);
|
||||
extern int p9hangup(int);
|
||||
extern int p9listen(char*, char*);
|
||||
extern char* p9netmkaddr(char*, char*, char*);
|
||||
extern int p9reject(int, char*, char*);
|
||||
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define accept p9accept
|
||||
#define announce p9announce
|
||||
#define dial p9dial
|
||||
#define setnetmtpt p9setnetmtpt
|
||||
#define hangup p9hangup
|
||||
#define listen p9listen
|
||||
#define netmkaddr p9netmkaddr
|
||||
#define reject p9reject
|
||||
#endif
|
||||
|
||||
/*
|
||||
* encryption
|
||||
*/
|
||||
extern int pushssl(int, char*, char*, char*, int*);
|
||||
extern int pushtls(int, char*, char*, int, char*, char*);
|
||||
|
||||
/*
|
||||
* network services
|
||||
*/
|
||||
typedef struct NetConnInfo NetConnInfo;
|
||||
struct NetConnInfo
|
||||
{
|
||||
char *dir; /* connection directory */
|
||||
char *root; /* network root */
|
||||
char *spec; /* binding spec */
|
||||
char *lsys; /* local system */
|
||||
char *lserv; /* local service */
|
||||
char *rsys; /* remote system */
|
||||
char *rserv; /* remote service */
|
||||
};
|
||||
extern NetConnInfo* getnetconninfo(char*, int);
|
||||
extern void freenetconninfo(NetConnInfo*);
|
||||
|
||||
/*
|
||||
* system calls
|
||||
*
|
||||
*/
|
||||
#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 */
|
||||
|
||||
/* Segattch */
|
||||
#define SG_RONLY 0040 /* read only */
|
||||
#define SG_CEXEC 0100 /* detach on exec */
|
||||
|
||||
#define NCONT 0 /* continue after note */
|
||||
#define NDFLT 1 /* terminate after note */
|
||||
#define NSAVE 2 /* clear note but hold state */
|
||||
#define NRSTR 3 /* restore saved state */
|
||||
|
||||
/* 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 DMREAD 0x4 /* mode bit for read permission */
|
||||
#define DMWRITE 0x2 /* mode bit for write permission */
|
||||
#define DMEXEC 0x1 /* mode bit for execute permission */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef RFFDG
|
||||
#undef RFNOTEG
|
||||
#undef RFPROC
|
||||
#undef RFMEM
|
||||
#undef RFNOWAIT
|
||||
#undef RFCFDG
|
||||
#undef RFNAMEG
|
||||
#undef RFENVG
|
||||
#undef RFCENVG
|
||||
#undef RFCFDG
|
||||
#undef RFCNAMEG
|
||||
#endif
|
||||
|
||||
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) */
|
||||
};
|
||||
|
||||
extern int ffork(int, void(*)(void*), void*);
|
||||
|
||||
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;
|
||||
|
||||
/* keep /sys/src/ape/lib/ap/plan9/sys9.h in sync with this -rsc */
|
||||
typedef
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
} Waitmsg;
|
||||
|
||||
typedef
|
||||
struct IOchunk
|
||||
{
|
||||
void *addr;
|
||||
ulong len;
|
||||
} IOchunk;
|
||||
|
||||
extern void _exits(char*);
|
||||
|
||||
extern void abort(void);
|
||||
extern int p9access(char*, int);
|
||||
extern long p9alarm(ulong);
|
||||
extern int await(char*, int);
|
||||
extern int awaitnohang(char*, int);
|
||||
/* extern int bind(char*, char*, int); give up */
|
||||
/* extern int brk(void*); <unistd.h> */
|
||||
extern int p9chdir(char*);
|
||||
extern int close(int);
|
||||
extern int p9create(char*, int, ulong);
|
||||
extern int p9dup(int, int);
|
||||
extern int errstr(char*, uint);
|
||||
extern int p9exec(char*, char*[]);
|
||||
/* extern int execl(char*, ...); <unistd.h> */
|
||||
/* extern int fork(void); <unistd.h> */
|
||||
extern int p9rfork(int);
|
||||
/* not implemented
|
||||
extern int fauth(int, char*);
|
||||
extern int fstat(int, uchar*, int);
|
||||
extern int fwstat(int, uchar*, int);
|
||||
extern int fversion(int, int, char*, int);
|
||||
extern int mount(int, int, char*, int, char*);
|
||||
extern int unmount(char*, char*);
|
||||
*/
|
||||
extern int noted(int);
|
||||
extern int notify(void(*)(void*, char*));
|
||||
extern int p9open(char*, int);
|
||||
extern int fd2path(int, char*, int);
|
||||
extern int p9pipe(int*);
|
||||
/*
|
||||
* use defs from <unistd.h>
|
||||
extern long pread(int, void*, long, vlong);
|
||||
extern long preadv(int, IOchunk*, int, vlong);
|
||||
extern long pwrite(int, void*, long, vlong);
|
||||
extern long pwritev(int, IOchunk*, int, vlong);
|
||||
extern long read(int, void*, long);
|
||||
*/
|
||||
extern long readn(int, void*, long);
|
||||
/* extern long readv(int, IOchunk*, int); <unistd.h> */
|
||||
extern int remove(const char*);
|
||||
/* extern void* sbrk(ulong); <unistd.h> */
|
||||
/* extern long oseek(int, long, int); */
|
||||
extern vlong p9seek(int, vlong, int);
|
||||
/* give up
|
||||
extern long segattach(int, char*, void*, ulong);
|
||||
extern int segbrk(void*, void*);
|
||||
extern int segdetach(void*);
|
||||
extern int segflush(void*, ulong);
|
||||
extern int segfree(void*, ulong);
|
||||
*/
|
||||
extern int p9sleep(long);
|
||||
/* extern int stat(char*, uchar*, int); give up */
|
||||
extern Waitmsg* p9wait(void);
|
||||
extern Waitmsg* waitnohang(void);
|
||||
extern int p9waitpid(void);
|
||||
/* <unistd.h>
|
||||
extern long write(int, void*, long);
|
||||
extern long writev(int, IOchunk*, int);
|
||||
*/
|
||||
/* extern int wstat(char*, uchar*, int); give up */
|
||||
extern ulong rendezvous(ulong, ulong);
|
||||
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define alarm p9alarm
|
||||
#define dup p9dup
|
||||
#define exec p9exec
|
||||
#define seek p9seek
|
||||
#define sleep p9sleep
|
||||
#define wait p9wait
|
||||
#define waitpid p9waitpid
|
||||
#define rfork p9rfork
|
||||
#define access p9access
|
||||
#define create p9create
|
||||
#define open p9open
|
||||
#define pipe p9pipe
|
||||
#endif
|
||||
|
||||
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); <unistd.h> */
|
||||
/* extern int getppid(void); */
|
||||
extern void rerrstr(char*, uint);
|
||||
extern char* sysname(void);
|
||||
extern void werrstr(char*, ...);
|
||||
extern char* getns(void);
|
||||
extern char* get9root(void);
|
||||
extern char* unsharp(char*);
|
||||
extern int sendfd(int, int);
|
||||
extern int recvfd(int);
|
||||
extern int post9pservice(int, char*);
|
||||
|
||||
/* external names that we don't want to step on */
|
||||
#ifndef NOPLAN9DEFINES
|
||||
#define main p9main
|
||||
#endif
|
||||
|
||||
/* compiler directives on plan 9 */
|
||||
#define USED(x) if(x){}else{}
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
/* command line */
|
||||
extern char *argv0;
|
||||
extern void __fixargv0(void);
|
||||
#define ARGBEGIN for((argv0?0:(argv0=(__fixargv0(),*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
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* _LIB9_H_ */
|
||||
|
|
93
include/u.h
93
include/u.h
|
@ -0,0 +1,93 @@
|
|||
#ifndef _U_H_
|
||||
#define _U_H_ 1
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _BSD_SOURCE 1
|
||||
#define _SVID_SOURCE 1
|
||||
#define _XOPEN_SOURCE 1000
|
||||
#define _XOPEN_SOURCE_EXTENDED 1
|
||||
#define _LARGEFILE64_SOURCE 1
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#define __EXTENSIONS__ 1 /* SunOS */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <setjmp.h>
|
||||
#include <stddef.h>
|
||||
#include <utf.h>
|
||||
#include <fmt.h>
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
* OS-specific crap
|
||||
*/
|
||||
#define _NEEDUCHAR 1
|
||||
#define _NEEDUSHORT 1
|
||||
#define _NEEDUINT 1
|
||||
#define _NEEDULONG 1
|
||||
|
||||
typedef long p9jmp_buf[sizeof(sigjmp_buf)/sizeof(long)];
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/types.h>
|
||||
# if defined(__USE_MISC)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__sun__)
|
||||
# include <sys/types.h>
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# if !defined(_POSIX_SOURCE)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
# include <sys/types.h>
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# define _NEEDLL 1
|
||||
#endif
|
||||
|
||||
typedef signed char schar;
|
||||
typedef unsigned int u32int;
|
||||
#ifdef _NEEDUCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#ifdef _NEEDUSHORT
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
#ifdef _NEEDUINT
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#ifdef _NEEDULONG
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long long vlong;
|
||||
typedef uvlong u64int;
|
||||
typedef uchar u8int;
|
||||
typedef ushort u16int;
|
||||
|
||||
#undef _NEEDUCHAR
|
||||
#undef _NEEDUSHORT
|
||||
#undef _NEEDUINT
|
||||
#undef _NEEDULONG
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -1150,7 +1150,7 @@ rewritehdr(Fcall *f, uchar *pkt)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _LIB9_H_
|
||||
#ifdef _LIBC_H_
|
||||
/* unix select-based polling */
|
||||
struct Ioproc
|
||||
{
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
#include "9term.h"
|
||||
|
||||
#define fatal sysfatal
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ctype.h>
|
||||
#include <draw.h>
|
||||
#include <thread.h>
|
||||
#include <mouse.h>
|
||||
#include <cursor.h>
|
||||
#include <keyboard.h>
|
||||
#include <frame.h>
|
||||
#include <plumb.h>
|
||||
#include <complete.h>
|
||||
#include "term.h"
|
||||
|
||||
typedef struct Text Text;
|
||||
typedef struct Readbuf Readbuf;
|
||||
|
||||
enum
|
||||
{
|
||||
/* these are chosen to use malloc()'s properties well */
|
||||
HiWater = 640000, /* max size of history */
|
||||
LoWater = 330000, /* min size of history after max'ed */
|
||||
LoWater = 400000, /* min size of history after max'ed */
|
||||
MinWater = 20000,
|
||||
};
|
||||
|
||||
/* various geometric paramters */
|
||||
|
@ -30,21 +39,22 @@ enum
|
|||
Scroll,
|
||||
};
|
||||
|
||||
|
||||
#define SCROLLKEY Kdown
|
||||
#define ESC 0x1B
|
||||
#define CUT 0x18 /* ctrl-x */
|
||||
#define COPY 0x03 /* crtl-c */
|
||||
#define PASTE 0x16 /* crtl-v */
|
||||
#define BACKSCROLLKEY Kup
|
||||
|
||||
#define READBUFSIZE 8192
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
|
||||
struct Text
|
||||
{
|
||||
Frame *f; /* frame ofr terminal */
|
||||
Mouse m;
|
||||
uint nr; /* num of runes in term */
|
||||
uint maxr; /* max num of runes in r */
|
||||
Rune *r; /* runes for term */
|
||||
uint nraw; /* num of runes in raw buffer */
|
||||
Rune *raw; /* raw buffer */
|
||||
|
@ -72,7 +82,6 @@ void fill(void);
|
|||
void tcheck(void);
|
||||
void updatesel(void);
|
||||
void doreshape(void);
|
||||
void rcstart(int fd[2], int, char**);
|
||||
void runewrite(Rune*, int);
|
||||
void consread(void);
|
||||
void conswrite(char*, int);
|
||||
|
@ -99,11 +108,10 @@ void scrdraw(void);
|
|||
void scroll(int);
|
||||
void hostproc(void *arg);
|
||||
void hoststart(void);
|
||||
int getchildwd(int, char*, int);
|
||||
void plumbstart(void);
|
||||
void plumb(uint, uint);
|
||||
void plumbclick(uint*, uint*);
|
||||
int getpts(int fd[], char *slave);
|
||||
uint insert(Rune*, int, uint, int);
|
||||
|
||||
#define runemalloc(n) malloc((n)*sizeof(Rune))
|
||||
#define runerealloc(a, n) realloc(a, (n)*sizeof(Rune))
|
||||
|
@ -115,7 +123,7 @@ int rawon; /* raw mode */
|
|||
int scrolling; /* window scrolls */
|
||||
int clickmsec; /* time of last click */
|
||||
uint clickq0; /* point of last click */
|
||||
int rcfd[2];
|
||||
int rcfd;
|
||||
int rcpid;
|
||||
int maxtab;
|
||||
int use9wm;
|
||||
|
@ -211,7 +219,7 @@ threadmain(int argc, char *argv[])
|
|||
|
||||
mc = initmouse(nil, screen);
|
||||
kc = initkeyboard(nil);
|
||||
rcstart(rcfd, argc, argv);
|
||||
rcpid = rcstart(argc, argv, &rcfd);
|
||||
hoststart();
|
||||
plumbstart();
|
||||
|
||||
|
@ -265,8 +273,9 @@ hostproc(void *arg)
|
|||
|
||||
i = 0;
|
||||
for(;;){
|
||||
/* Let typing have a go -- maybe there's a rubout waiting. */
|
||||
i = 1-i; /* toggle */
|
||||
n = threadread(rcfd[0], rcbuf[i].data, sizeof rcbuf[i].data);
|
||||
n = threadread(rcfd, rcbuf[i].data, sizeof rcbuf[i].data);
|
||||
if(n <= 0){
|
||||
if(n < 0)
|
||||
fprint(2, "9term: host read error: %r\n");
|
||||
|
@ -308,7 +317,7 @@ loop(void)
|
|||
a[2].op = CHANNOP;;
|
||||
switch(alt(a)) {
|
||||
default:
|
||||
fatal("impossible");
|
||||
sysfatal("impossible");
|
||||
case 0:
|
||||
t.m = mc->m;
|
||||
mouse();
|
||||
|
@ -330,23 +339,23 @@ void
|
|||
doreshape(void)
|
||||
{
|
||||
if(getwindow(display, Refnone) < 0)
|
||||
fatal("can't reattach to window");
|
||||
sysfatal("can't reattach to window");
|
||||
draw(screen, screen->r, cols[BACK], nil, ZP);
|
||||
geom();
|
||||
scrdraw();
|
||||
}
|
||||
|
||||
struct winsize ows;
|
||||
|
||||
void
|
||||
geom(void)
|
||||
{
|
||||
struct winsize ws;
|
||||
Point p;
|
||||
Rectangle r;
|
||||
|
||||
r = screen->r;
|
||||
scrollr = screen->r;
|
||||
r.min.y++;
|
||||
r.max.y--;
|
||||
|
||||
scrollr = r;
|
||||
scrollr.max.x = r.min.x+Scrollwid;
|
||||
lastsr = Rect(0,0,0,0);
|
||||
|
||||
|
@ -362,13 +371,7 @@ geom(void)
|
|||
if(p.x == 0 || p.y == 0)
|
||||
return;
|
||||
|
||||
ws.ws_row = Dy(r)/p.y;
|
||||
ws.ws_col = Dx(r)/p.x;
|
||||
ws.ws_xpixel = Dx(r);
|
||||
ws.ws_ypixel = Dy(r);
|
||||
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
|
||||
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
|
||||
fprint(2, "ioctl: %r\n");
|
||||
updatewinsize(Dy(r)/p.y, Dx(r)/p.x, Dx(r), Dy(r));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -585,7 +588,10 @@ domenu2(int but)
|
|||
show(t.q0);
|
||||
break;
|
||||
case Send:
|
||||
if(t.q0 != t.q1)
|
||||
snarf();
|
||||
else
|
||||
snarfupdate();
|
||||
t.q0 = t.q1 = t.nr;
|
||||
updatesel();
|
||||
paste(t.snarf, t.nsnarf, 1);
|
||||
|
@ -605,37 +611,182 @@ domenu2(int but)
|
|||
plumb(t.q0, t.q1);
|
||||
break;
|
||||
default:
|
||||
fatal("bad menu item");
|
||||
sysfatal("bad menu item");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
windfilewidth(uint q0, int oneelement)
|
||||
{
|
||||
uint q;
|
||||
Rune r;
|
||||
|
||||
q = q0;
|
||||
while(q > 0){
|
||||
r = t.r[q-1];
|
||||
if(r<=' ')
|
||||
break;
|
||||
if(oneelement && r=='/')
|
||||
break;
|
||||
--q;
|
||||
}
|
||||
return q0-q;
|
||||
}
|
||||
|
||||
void
|
||||
showcandidates(Completion *c)
|
||||
{
|
||||
int i;
|
||||
Fmt f;
|
||||
Rune *rp;
|
||||
uint nr, qline, q0;
|
||||
char *s;
|
||||
|
||||
runefmtstrinit(&f);
|
||||
if (c->nmatch == 0)
|
||||
s = "[no matches in ";
|
||||
else
|
||||
s = "[";
|
||||
if(c->nfile > 32)
|
||||
fmtprint(&f, "%s%d files]\n", s, c->nfile);
|
||||
else{
|
||||
fmtprint(&f, "%s", s);
|
||||
for(i=0; i<c->nfile; i++){
|
||||
if(i > 0)
|
||||
fmtprint(&f, " ");
|
||||
fmtprint(&f, "%s", c->filename[i]);
|
||||
}
|
||||
fmtprint(&f, "]\n");
|
||||
}
|
||||
/* place text at beginning of line before host point */
|
||||
qline = t.qh;
|
||||
while(qline>0 && t.r[qline-1] != '\n')
|
||||
qline--;
|
||||
|
||||
rp = runefmtstrflush(&f);
|
||||
nr = runestrlen(rp);
|
||||
|
||||
q0 = t.q0;
|
||||
q0 += insert(rp, nr, qline, 0) - qline;
|
||||
free(rp);
|
||||
t.q0 = q0+nr;
|
||||
t.q1 = q0+nr;
|
||||
updatesel();
|
||||
}
|
||||
|
||||
Rune*
|
||||
namecomplete(void)
|
||||
{
|
||||
int nstr, npath;
|
||||
Rune *rp, *path, *str;
|
||||
Completion *c;
|
||||
char *s, *dir, *root;
|
||||
|
||||
/* control-f: filename completion; works back to white space or / */
|
||||
if(t.q0<t.nr && t.r[t.q0]>' ') /* must be at end of word */
|
||||
return nil;
|
||||
nstr = windfilewidth(t.q0, TRUE);
|
||||
str = runemalloc(nstr);
|
||||
runemove(str, t.r+(t.q0-nstr), nstr);
|
||||
npath = windfilewidth(t.q0-nstr, FALSE);
|
||||
path = runemalloc(npath);
|
||||
runemove(path, t.r+(t.q0-nstr-npath), npath);
|
||||
rp = nil;
|
||||
|
||||
/* is path rooted? if not, we need to make it relative to window path */
|
||||
if(npath>0 && path[0]=='/'){
|
||||
dir = malloc(UTFmax*npath+1);
|
||||
sprint(dir, "%.*S", npath, path);
|
||||
}else{
|
||||
if(strcmp(wdir, "") == 0)
|
||||
root = ".";
|
||||
else
|
||||
root = wdir;
|
||||
dir = malloc(strlen(root)+1+UTFmax*npath+1);
|
||||
sprint(dir, "%s/%.*S", root, npath, path);
|
||||
}
|
||||
dir = cleanname(dir);
|
||||
|
||||
s = smprint("%.*S", nstr, str);
|
||||
c = complete(dir, s);
|
||||
free(s);
|
||||
if(c == nil)
|
||||
goto Return;
|
||||
|
||||
if(!c->advance)
|
||||
showcandidates(c);
|
||||
|
||||
if(c->advance)
|
||||
rp = runesmprint("%s", c->string);
|
||||
|
||||
Return:
|
||||
freecompletion(c);
|
||||
free(dir);
|
||||
free(path);
|
||||
free(str);
|
||||
return rp;
|
||||
}
|
||||
|
||||
void
|
||||
key(Rune r)
|
||||
{
|
||||
uint sig;
|
||||
Rune *rp;
|
||||
int nr;
|
||||
|
||||
if(r == 0)
|
||||
return;
|
||||
if(r==SCROLLKEY){ /* scroll key */
|
||||
switch(r){
|
||||
case Kpgup:
|
||||
setorigin(backnl(t.org, t.f->maxlines*2/3), 1);
|
||||
return;
|
||||
case Kpgdown:
|
||||
setorigin(line2q(t.f->maxlines*2/3), 1);
|
||||
if(t.qh<=t.org+t.f->nchars)
|
||||
consread();
|
||||
return;
|
||||
}else if(r == BACKSCROLLKEY){
|
||||
setorigin(backnl(t.org, t.f->maxlines*2/3), 1);
|
||||
case Kup:
|
||||
setorigin(backnl(t.org, t.f->maxlines/3), 1);
|
||||
return;
|
||||
}else if(r == CUT){
|
||||
case Kdown:
|
||||
setorigin(line2q(t.f->maxlines/3), 1);
|
||||
if(t.qh<=t.org+t.f->nchars)
|
||||
consread();
|
||||
return;
|
||||
case Kleft:
|
||||
if(t.q0 > 0){
|
||||
t.q0--;
|
||||
t.q1 = t.q0;
|
||||
updatesel();
|
||||
show(t.q0);
|
||||
}
|
||||
return;
|
||||
case Kright:
|
||||
if(t.q1 < t.nr){
|
||||
t.q1++;
|
||||
t.q0 = t.q1;
|
||||
updatesel();
|
||||
show(t.q1);
|
||||
}
|
||||
return;
|
||||
case Khome:
|
||||
show(0);
|
||||
return;
|
||||
case Kend:
|
||||
case 0x05:
|
||||
show(t.nr);
|
||||
return;
|
||||
case CUT:
|
||||
snarf();
|
||||
cut();
|
||||
if(scrolling)
|
||||
show(t.q0);
|
||||
return;
|
||||
}else if(r == COPY){
|
||||
case COPY:
|
||||
snarf();
|
||||
if(scrolling)
|
||||
show(t.q0);
|
||||
return;
|
||||
}else if(r == PASTE){
|
||||
case PASTE:
|
||||
snarfupdate();
|
||||
paste(t.snarf, t.nsnarf, 0);
|
||||
if(scrolling)
|
||||
|
@ -661,19 +812,21 @@ key(Rune r)
|
|||
snarf();
|
||||
|
||||
switch(r) {
|
||||
case 0x03: /* ^C: send interrupt */
|
||||
case 0x7F: /* DEL: send interrupt */
|
||||
t.qh = t.q0 = t.q1 = t.nr;
|
||||
show(t.q0);
|
||||
goto Default;
|
||||
fprint(2, "send interrupt to %d group\n", rcpid);
|
||||
#ifdef TIOCSIG
|
||||
sig = 2; /* SIGINT */
|
||||
if(ioctl(rcfd[0], TIOCSIG, &sig) < 0)
|
||||
fprint(2, "sending interrupt: %r\n");
|
||||
#else
|
||||
postnote(PNGROUP, rcpid, "interrupt");
|
||||
#endif
|
||||
write(rcfd, "\x7F", 1);
|
||||
break;
|
||||
case 0x06: /* ^F: file name completion */
|
||||
case Kins: /* Insert: file name completion */
|
||||
rp = namecomplete();
|
||||
if(rp == nil)
|
||||
return;
|
||||
nr = runestrlen(rp);
|
||||
paste(rp, nr, 1);
|
||||
free(rp);
|
||||
return;
|
||||
case 0x08: /* ^H: erase character */
|
||||
case 0x15: /* ^U: erase line */
|
||||
case 0x17: /* ^W: erase word */
|
||||
|
@ -682,7 +835,6 @@ fprint(2, "send interrupt to %d group\n", rcpid);
|
|||
cut();
|
||||
break;
|
||||
default:
|
||||
Default:
|
||||
paste(&r, 1, 1);
|
||||
break;
|
||||
}
|
||||
|
@ -773,7 +925,7 @@ consread(void)
|
|||
}
|
||||
/* take out control-d when not doing a zero length write */
|
||||
n = p-buf;
|
||||
if(write(rcfd[1], buf, n) < 0)
|
||||
if(write(rcfd, buf, n) < 0)
|
||||
exits(0);
|
||||
/* mallocstats(); */
|
||||
}
|
||||
|
@ -833,7 +985,6 @@ conswrite(char *p, int n)
|
|||
void
|
||||
runewrite(Rune *r, int n)
|
||||
{
|
||||
uint m;
|
||||
int i;
|
||||
uint initial;
|
||||
uint q0, q1;
|
||||
|
@ -896,37 +1047,7 @@ runewrite(Rune *r, int n)
|
|||
updatesel();
|
||||
}
|
||||
|
||||
if(t.nr>HiWater && t.qh>=t.org){
|
||||
m = HiWater-LoWater;
|
||||
if(m > t.org);
|
||||
m = t.org;
|
||||
t.org -= m;
|
||||
t.qh -= m;
|
||||
if(t.q0 > m)
|
||||
t.q0 -= m;
|
||||
else
|
||||
t.q0 = 0;
|
||||
if(t.q1 > m)
|
||||
t.q1 -= m;
|
||||
else
|
||||
t.q1 = 0;
|
||||
t.nr -= m;
|
||||
runemove(t.r, t.r+m, t.nr);
|
||||
}
|
||||
t.r = runerealloc(t.r, t.nr+n);
|
||||
runemove(t.r+t.qh+n, t.r+t.qh, t.nr-t.qh);
|
||||
runemove(t.r+t.qh, r, n);
|
||||
t.nr += n;
|
||||
if(t.qh < t.org)
|
||||
t.org += n;
|
||||
else if(t.qh <= t.f->nchars+t.org)
|
||||
frinsert(t.f, r, r+n, t.qh-t.org);
|
||||
if (t.qh <= t.q0)
|
||||
t.q0 += n;
|
||||
if (t.qh <= t.q1)
|
||||
t.q1 += n;
|
||||
t.qh += n;
|
||||
updatesel();
|
||||
insert(r, n, t.qh, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1009,12 +1130,83 @@ snarf(void)
|
|||
putsnarf(sbuf);
|
||||
}
|
||||
|
||||
uint
|
||||
min(uint x, uint y)
|
||||
{
|
||||
if(x < y)
|
||||
return x;
|
||||
return y;
|
||||
}
|
||||
|
||||
uint
|
||||
max(uint x, uint y)
|
||||
{
|
||||
if(x > y)
|
||||
return x;
|
||||
return y;
|
||||
}
|
||||
|
||||
uint
|
||||
insert(Rune *r, int n, uint q0, int hostwrite)
|
||||
{
|
||||
uint m;
|
||||
|
||||
if(n == 0)
|
||||
return q0;
|
||||
if(t.nr+n>HiWater && q0>=t.org && q0>=t.qh){
|
||||
m = min(HiWater-LoWater, min(t.org, t.qh));
|
||||
t.org -= m;
|
||||
t.qh -= m;
|
||||
if(t.q0 > m)
|
||||
t.q0 -= m;
|
||||
else
|
||||
t.q0 = 0;
|
||||
if(t.q1 > m)
|
||||
t.q1 -= m;
|
||||
else
|
||||
t.q1 = 0;
|
||||
t.nr -= m;
|
||||
runemove(t.r, t.r+m, t.nr);
|
||||
q0 -= m;
|
||||
}
|
||||
if(t.nr+n > t.maxr){
|
||||
/*
|
||||
* Minimize realloc breakage:
|
||||
* Allocate at least MinWater
|
||||
* Double allocation size each time
|
||||
* But don't go much above HiWater
|
||||
*/
|
||||
m = max(min(2*(t.nr+n), HiWater), t.nr+n)+MinWater;
|
||||
if(m > HiWater)
|
||||
m = max(HiWater+MinWater, t.nr+n);
|
||||
if(m > t.maxr){
|
||||
t.r = runerealloc(t.r, m);
|
||||
t.maxr = m;
|
||||
}
|
||||
}
|
||||
runemove(t.r+q0+n, t.r+q0, t.nr-q0);
|
||||
runemove(t.r+q0, r, n);
|
||||
t.nr += n;
|
||||
/* if output touches, advance selection, not qh; works best for keyboard and output */
|
||||
if(q0 <= t.q1)
|
||||
t.q1 += n;
|
||||
if(q0 <= t.q0)
|
||||
t.q0 += n;
|
||||
if(q0 < t.qh || (q0==t.qh && hostwrite))
|
||||
t.qh += n;
|
||||
else
|
||||
consread();
|
||||
if(q0 < t.org)
|
||||
t.org += n;
|
||||
else if(q0 <= t.org+t.f->nchars)
|
||||
frinsert(t.f, r, r+n, q0-t.org);
|
||||
return q0;
|
||||
}
|
||||
|
||||
void
|
||||
paste(Rune *r, int n, int advance)
|
||||
{
|
||||
Rune *rbuf;
|
||||
uint m;
|
||||
uint q0;
|
||||
|
||||
if(rawon && t.q0==t.nr){
|
||||
addraw(r, n);
|
||||
|
@ -1024,6 +1216,7 @@ paste(Rune *r, int n, int advance)
|
|||
cut();
|
||||
if(n == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* if this is a button2 execute then we might have been passed
|
||||
* runes inside the buffer. must save them before realloc.
|
||||
|
@ -1035,36 +1228,7 @@ paste(Rune *r, int n, int advance)
|
|||
r = rbuf;
|
||||
}
|
||||
|
||||
if(t.nr>HiWater && t.q0>=t.org && t.q0>=t.qh){
|
||||
m = HiWater-LoWater;
|
||||
if(m > t.org)
|
||||
m = t.org;
|
||||
if(m > t.qh);
|
||||
m = t.qh;
|
||||
t.org -= m;
|
||||
t.qh -= m;
|
||||
t.q0 -= m;
|
||||
t.q1 -= m;
|
||||
t.nr -= m;
|
||||
runemove(t.r, t.r+m, t.nr);
|
||||
}
|
||||
|
||||
t.r = runerealloc(t.r, t.nr+n);
|
||||
q0 = t.q0;
|
||||
runemove(t.r+q0+n, t.r+q0, t.nr-q0);
|
||||
runemove(t.r+q0, r, n);
|
||||
t.nr += n;
|
||||
if(q0 < t.qh)
|
||||
t.qh += n;
|
||||
else
|
||||
consread();
|
||||
if(q0 < t.org)
|
||||
t.org += n;
|
||||
else if(q0 <= t.f->nchars+t.org)
|
||||
frinsert(t.f, r, r+n, q0-t.org);
|
||||
if(advance)
|
||||
t.q0 += n;
|
||||
t.q1 += n;
|
||||
insert(r, n, t.q0, 0);
|
||||
updatesel();
|
||||
free(rbuf);
|
||||
}
|
||||
|
@ -1321,61 +1485,6 @@ clickmatch(int cl, int cr, int dir, uint *q)
|
|||
return cl=='\n' && nest==1;
|
||||
}
|
||||
|
||||
void
|
||||
rcstart(int fd[2], int argc, char **argv)
|
||||
{
|
||||
int pid;
|
||||
char *xargv[3];
|
||||
char slave[256];
|
||||
int sfd;
|
||||
|
||||
if(argc == 0){
|
||||
argc = 2;
|
||||
argv = xargv;
|
||||
argv[0] = getenv("SHELL");
|
||||
if(argv[0] == 0)
|
||||
argv[0] = "rc";
|
||||
argv[1] = "-i";
|
||||
argv[2] = 0;
|
||||
}
|
||||
/*
|
||||
* fd0 is slave (tty), fd1 is master (pty)
|
||||
*/
|
||||
fd[0] = fd[1] = -1;
|
||||
if(getpts(fd, slave) < 0)
|
||||
fprint(2, "getpts: %r\n");
|
||||
|
||||
switch(pid = fork()) {
|
||||
case 0:
|
||||
putenv("TERM", "9term");
|
||||
close(fd[1]);
|
||||
setsid();
|
||||
// tcsetpgrp(0, pid);
|
||||
sfd = open(slave, ORDWR);
|
||||
if(sfd < 0)
|
||||
fprint(2, "open %s: %r\n", slave);
|
||||
if(ioctl(sfd, TIOCSCTTY, 0) < 0)
|
||||
fprint(2, "ioctl TIOCSCTTY: %r\n");
|
||||
// ioctl(sfd, I_PUSH, "ptem");
|
||||
// ioctl(sfd, I_PUSH, "ldterm");
|
||||
dup(sfd, 0);
|
||||
dup(sfd, 1);
|
||||
dup(sfd, 2);
|
||||
system("stty tabs -onlcr -echo erase ^h intr ^?");
|
||||
execvp(argv[0], argv);
|
||||
fprint(2, "exec %s failed: %r\n", argv[0]);
|
||||
_exits("oops");
|
||||
break;
|
||||
case -1:
|
||||
fatal("proc failed: %r");
|
||||
break;
|
||||
}
|
||||
close(fd[0]);
|
||||
fd[0] = fd[1];
|
||||
|
||||
rcpid = pid;
|
||||
}
|
||||
|
||||
void
|
||||
tcheck(void)
|
||||
{
|
||||
|
@ -1421,7 +1530,7 @@ scrdraw(void)
|
|||
freeimage(scrx);
|
||||
scrx = allocimage(display, Rect(0, 0, 32, r.max.y), screen->chan, 1, DPaleyellow);
|
||||
if(scrx == 0)
|
||||
fatal("scroll balloc");
|
||||
sysfatal("scroll balloc");
|
||||
}
|
||||
r1.min.x = 0;
|
||||
r1.max.x = Dx(r);
|
||||
|
@ -1525,16 +1634,11 @@ plumb(uint q0, uint q1)
|
|||
char *p;
|
||||
int i, p0, n;
|
||||
char cbuf[100];
|
||||
char *w;
|
||||
|
||||
if(getchildwd(rcpid, childwdir, sizeof childwdir) == 0)
|
||||
w = childwdir;
|
||||
else
|
||||
w = wdir;
|
||||
pm = malloc(sizeof(Plumbmsg));
|
||||
pm->src = strdup("9term");
|
||||
pm->dst = 0;
|
||||
pm->wdir = strdup(w);
|
||||
pm->wdir = strdup(wdir);
|
||||
pm->type = strdup("text");
|
||||
pm->data = nil;
|
||||
if(q1 > q0)
|
||||
|
|
|
@ -1,19 +1,4 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ctype.h>
|
||||
#include <draw.h>
|
||||
#include <thread.h>
|
||||
#include <mouse.h>
|
||||
#include <cursor.h>
|
||||
#include <keyboard.h>
|
||||
#include <frame.h>
|
||||
#include <plumb.h>
|
||||
#include <termios.h>
|
||||
#include <sys/termios.h>
|
||||
#ifdef __linux__
|
||||
#include <pty.h>
|
||||
#endif
|
||||
|
||||
extern int getchildwd(int, char*, int);
|
||||
extern int getpts(int[], char*);
|
||||
|
||||
extern int childpty(int[], char*);
|
||||
extern void updatewinsize(int, int, int, int);
|
||||
extern int rcfd[];
|
||||
|
|
|
@ -1,17 +1,43 @@
|
|||
#include "9term.h"
|
||||
#include <termios.h>
|
||||
#include <sys/termios.h>
|
||||
#include <libutil.h>
|
||||
|
||||
int
|
||||
getchildwd(int pid, char *wdir, int bufn)
|
||||
{
|
||||
USED(pid);
|
||||
USED(wdir);
|
||||
USED(bufn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
getpts(int fd[], char *slave)
|
||||
{
|
||||
return openpty(&fd[1], &fd[0], slave, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
childpty(int fd[], char *slave)
|
||||
{
|
||||
int sfd;
|
||||
|
||||
close(fd[1]);
|
||||
setsid();
|
||||
sfd = open(slave, ORDWR);
|
||||
if(sfd < 0)
|
||||
sysfatal("open %s: %r\n", slave);
|
||||
if(ioctl(sfd, TIOCSCTTY, 0) < 0)
|
||||
fprint(2, "ioctl TIOCSCTTY: %r\n");
|
||||
return sfd;
|
||||
}
|
||||
|
||||
struct winsize ows;
|
||||
|
||||
void
|
||||
updatewinsize(int row, int col, int dx, int dy)
|
||||
{
|
||||
struct winsize ws;
|
||||
|
||||
ws.ws_row = row;
|
||||
ws.ws_col = col;
|
||||
ws.ws_xpixel = dx;
|
||||
ws.ws_ypixel = dy;
|
||||
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
|
||||
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
|
||||
fprint(2, "ioctl: %r\n");
|
||||
ows = ws;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,46 @@
|
|||
#include <u.h>
|
||||
#include <termios.h>
|
||||
#include <sys/termios.h>
|
||||
#include <pty.h>
|
||||
#include <libc.h>
|
||||
#include "9term.h"
|
||||
|
||||
int
|
||||
getchildwd(int pid, char *wdir, int bufn)
|
||||
{
|
||||
char path[256];
|
||||
int n;
|
||||
|
||||
snprint(path, sizeof path, "/proc/%d/cwd", pid);
|
||||
n = readlink(path, wdir, bufn);
|
||||
if(n < 0)
|
||||
return -1;
|
||||
wdir[n] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
getpts(int fd[], char *slave)
|
||||
{
|
||||
openpty(&fd[1], &fd[0], slave, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
childpty(int fd[], char *slave)
|
||||
{
|
||||
int sfd;
|
||||
|
||||
close(fd[1]);
|
||||
setsid();
|
||||
sfd = open(slave, ORDWR);
|
||||
if(sfd < 0)
|
||||
sysfatal("open %s: %r\n", slave);
|
||||
if(ioctl(sfd, TIOCSCTTY, 0) < 0)
|
||||
fprint(2, "ioctl TIOCSCTTY: %r\n");
|
||||
return sfd;
|
||||
}
|
||||
|
||||
struct winsize ows;
|
||||
|
||||
void
|
||||
updatewinsize(int row, int col, int dx, int dy)
|
||||
{
|
||||
struct winsize ws;
|
||||
|
||||
ws.ws_row = row;
|
||||
ws.ws_col = col;
|
||||
ws.ws_xpixel = dx;
|
||||
ws.ws_ypixel = dy;
|
||||
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
|
||||
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
|
||||
fprint(2, "ioctl: %r\n");
|
||||
ows = ws;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
#include "9term.h"
|
||||
|
||||
int
|
||||
getchildwd(int pid, char *wdir, int bufn)
|
||||
{
|
||||
char path[256];
|
||||
char cwd[256];
|
||||
|
||||
if(getcwd(cwd, sizeof cwd) < 0)
|
||||
return -1;
|
||||
snprint(path, sizeof path, "/proc/%d/cwd", pid);
|
||||
if(chdir(path) < 0)
|
||||
return -1;
|
||||
if(getcwd(wdir, bufn) < 0)
|
||||
return -1;
|
||||
chdir(cwd);
|
||||
return 0;
|
||||
}
|
||||
#include <termios.h>
|
||||
#include <sys/termios.h>
|
||||
|
||||
int
|
||||
getpts(int fd[], char *slave)
|
||||
|
@ -28,3 +13,21 @@ getpts(int fd[], char *slave)
|
|||
fd[0] = open(slave, OREAD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct winsize ows;
|
||||
|
||||
void
|
||||
updatewinsize(int row, int col, int dx, int dy)
|
||||
{
|
||||
struct winsize ws;
|
||||
|
||||
ws.ws_row = row;
|
||||
ws.ws_col = col;
|
||||
ws.ws_xpixel = dx;
|
||||
ws.ws_ypixel = dy;
|
||||
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
|
||||
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
|
||||
fprint(2, "ioctl: %r\n");
|
||||
ows = ws;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
PLAN9=../../..
|
||||
<$PLAN9/src/mkhdr
|
||||
|
||||
TARG=9term
|
||||
TARG=9term win
|
||||
|
||||
OFILES=\
|
||||
9term.$O\
|
||||
rcstart.$O\
|
||||
$SYSNAME.$O\
|
||||
|
||||
SHORTLIB=frame draw plumb fs mux thread 9
|
||||
SHORTLIB=complete frame draw plumb fs mux thread 9
|
||||
|
||||
<$PLAN9/src/mkone
|
||||
<$PLAN9/src/mkmany
|
||||
|
||||
LDFLAGS=-L$X11/lib -lX11 -lutil
|
||||
|
||||
|
|
51
src/cmd/9term/rcstart.c
Normal file
51
src/cmd/9term/rcstart.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "term.h"
|
||||
|
||||
int
|
||||
rcstart(int argc, char **argv, int *pfd)
|
||||
{
|
||||
int pid;
|
||||
int fd[2];
|
||||
char *xargv[3];
|
||||
char slave[256];
|
||||
int sfd;
|
||||
|
||||
if(argc == 0){
|
||||
argc = 2;
|
||||
argv = xargv;
|
||||
argv[0] = getenv("SHELL");
|
||||
if(argv[0] == 0)
|
||||
argv[0] = "rc";
|
||||
argv[1] = "-i";
|
||||
argv[2] = 0;
|
||||
}
|
||||
/*
|
||||
* fd0 is slave (tty), fd1 is master (pty)
|
||||
*/
|
||||
fd[0] = fd[1] = -1;
|
||||
if(getpts(fd, slave) < 0)
|
||||
fprint(2, "getpts: %r\n");
|
||||
|
||||
|
||||
switch(pid = fork()) {
|
||||
case 0:
|
||||
putenv("TERM", "9term");
|
||||
sfd = childpty(fd, slave);
|
||||
dup(sfd, 0);
|
||||
dup(sfd, 1);
|
||||
dup(sfd, 2);
|
||||
system("stty tabs -onlcr -echo erase ^h intr ^?");
|
||||
execvp(argv[0], argv);
|
||||
fprint(2, "exec %s failed: %r\n", argv[0]);
|
||||
_exits("oops");
|
||||
break;
|
||||
case -1:
|
||||
sysfatal("proc failed: %r");
|
||||
break;
|
||||
}
|
||||
close(fd[0]);
|
||||
*pfd = fd[1];
|
||||
return pid;
|
||||
}
|
||||
|
5
src/cmd/9term/term.h
Normal file
5
src/cmd/9term/term.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
extern int getpts(int[], char*);
|
||||
extern int childpty(int[], char*);
|
||||
extern void updatewinsize(int, int, int, int);
|
||||
extern int rcfd;
|
||||
extern int rcstart(int, char*[], int*);
|
|
@ -3,6 +3,7 @@
|
|||
#include <thread.h>
|
||||
#include <fcall.h>
|
||||
#include <fs.h>
|
||||
#include "term.h"
|
||||
|
||||
#define EVENTSIZE 256
|
||||
#define STACK 32768
|
||||
|
@ -51,11 +52,11 @@ int ntypeb;
|
|||
int ntyper;
|
||||
int ntypebreak;
|
||||
int debug;
|
||||
int rcfd;
|
||||
|
||||
char *name;
|
||||
|
||||
char **prog;
|
||||
int p[2];
|
||||
Channel *cpid;
|
||||
Channel *cwait;
|
||||
int pid = -1;
|
||||
|
||||
|
@ -124,9 +125,11 @@ threadmain(int argc, char **argv)
|
|||
|
||||
prog = argv;
|
||||
|
||||
if(argc > 0)
|
||||
if(argc > 0){
|
||||
name = argv[0];
|
||||
else
|
||||
argc--;
|
||||
argv++;
|
||||
}else
|
||||
name = "gnot";
|
||||
|
||||
threadnotify(nopipes, 1);
|
||||
|
@ -156,14 +159,9 @@ threadmain(int argc, char **argv)
|
|||
*/
|
||||
fsunmount(fs);
|
||||
|
||||
if(pipe(p) < 0)
|
||||
sysfatal("pipe: %r");
|
||||
|
||||
cpid = chancreate(sizeof(ulong), 1);
|
||||
cwait = threadwaitchan();
|
||||
threadcreate(waitthread, nil, STACK);
|
||||
threadcreate(runproc, nil, STACK);
|
||||
pid = recvul(cpid);
|
||||
pid = rcstart(argc, argv, &rcfd);
|
||||
if(pid == -1)
|
||||
sysfatal("exec failed");
|
||||
|
||||
|
@ -179,30 +177,6 @@ threadmain(int argc, char **argv)
|
|||
stdinproc(nil);
|
||||
}
|
||||
|
||||
char *shell[] = { "rc", "-i", 0 };
|
||||
void
|
||||
runproc(void *v)
|
||||
{
|
||||
int fd[3];
|
||||
char *sh;
|
||||
|
||||
USED(v);
|
||||
|
||||
fd[0] = p[1];
|
||||
// fd[1] = bodyfd;
|
||||
// fd[2] = bodyfd;
|
||||
fd[1] = p[1];
|
||||
fd[2] = p[1];
|
||||
|
||||
if(prog[0] == nil){
|
||||
prog = shell;
|
||||
if((sh = getenv("SHELL")) != nil)
|
||||
shell[0] = sh;
|
||||
}
|
||||
threadexec(cpid, fd, prog[0], prog);
|
||||
threadexits(nil);
|
||||
}
|
||||
|
||||
void
|
||||
error(char *s)
|
||||
{
|
||||
|
@ -329,7 +303,7 @@ stdinproc(void *v)
|
|||
Fid *efd = eventfd;
|
||||
Fid *dfd = datafd;
|
||||
Fid *afd = addrfd;
|
||||
int fd0 = p[0];
|
||||
int fd0 = rcfd;
|
||||
Event e, e2, e3, e4;
|
||||
|
||||
USED(v);
|
||||
|
@ -426,7 +400,7 @@ stdinproc(void *v)
|
|||
void
|
||||
stdoutproc(void *v)
|
||||
{
|
||||
int fd1 = p[0];
|
||||
int fd1 = rcfd;
|
||||
Fid *afd = addrfd;
|
||||
Fid *dfd = datafd;
|
||||
int n, m, w, npart;
|
||||
|
@ -439,6 +413,8 @@ stdoutproc(void *v)
|
|||
buf = malloc(8192+UTFmax+1);
|
||||
npart = 0;
|
||||
for(;;){
|
||||
/* Let typing have a go -- maybe there's a rubout waiting. */
|
||||
yield();
|
||||
n = threadread(fd1, buf+npart, 8192);
|
||||
if(n < 0)
|
||||
error(nil);
|
||||
|
@ -556,7 +532,7 @@ addtype(int c, uint p0, char *b, int nb, int nr)
|
|||
for(i=0; i<nb; i+=w){
|
||||
w = chartorune(&r, b+i);
|
||||
if((r==0x7F||r==3) && c=='K'){
|
||||
postnote(PNGROUP, pid, "interrupt");
|
||||
write(rcfd, "\x7F", 1);
|
||||
/* toss all typing */
|
||||
q.p += ntyper+nr;
|
||||
ntypebreak = 0;
|
|
@ -161,7 +161,8 @@ threadmain(int argc, char *argv[])
|
|||
cerr = chancreate(sizeof(char*), 0);
|
||||
cedit = chancreate(sizeof(int), 0);
|
||||
cexit = chancreate(sizeof(int), 0);
|
||||
if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil){
|
||||
cwarn = chancreate(sizeof(void*), 1);
|
||||
if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil || cwarn==nil){
|
||||
fprint(2, "acme: can't create initial channels: %r\n");
|
||||
exits("channels");
|
||||
}
|
||||
|
@ -251,7 +252,7 @@ readfile(Column *c, char *s)
|
|||
|
||||
w = coladd(c, nil, nil, -1);
|
||||
cvttorunes(s, strlen(s), rb, &nb, &nr, nil);
|
||||
rs = cleanrname((Runestr){rb, nr});
|
||||
rs = cleanrname(runestr(rb, nr));
|
||||
winsetname(w, rs.r, rs.nr);
|
||||
textload(&w->body, 0, s, 1);
|
||||
w->body.file->mod = FALSE;
|
||||
|
@ -403,7 +404,6 @@ keyboardthread(void *v)
|
|||
winlock(t->w, 'K');
|
||||
wincommit(t->w, t);
|
||||
winunlock(t->w);
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
}
|
||||
alts[KTimer].c = nil;
|
||||
|
@ -430,7 +430,6 @@ keyboardthread(void *v)
|
|||
}
|
||||
if(nbrecv(keyboardctl->c, &r) > 0)
|
||||
goto casekeyboard;
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
break;
|
||||
}
|
||||
|
@ -447,7 +446,7 @@ mousethread(void *v)
|
|||
Plumbmsg *pm;
|
||||
Mouse m;
|
||||
char *act;
|
||||
enum { MResize, MMouse, MPlumb, NMALT };
|
||||
enum { MResize, MMouse, MPlumb, MWarnings, NMALT };
|
||||
static Alt alts[NMALT+1];
|
||||
|
||||
USED(v);
|
||||
|
@ -461,11 +460,18 @@ mousethread(void *v)
|
|||
alts[MPlumb].c = cplumb;
|
||||
alts[MPlumb].v = ±
|
||||
alts[MPlumb].op = CHANRCV;
|
||||
alts[MWarnings].c = cwarn;
|
||||
alts[MWarnings].v = nil;
|
||||
alts[MWarnings].op = CHANRCV;
|
||||
if(cplumb == nil)
|
||||
alts[MPlumb].op = CHANNOP;
|
||||
alts[NMALT].op = CHANEND;
|
||||
|
||||
for(;;){
|
||||
qlock(&row.lk);
|
||||
flushwarnings();
|
||||
qunlock(&row.lk);
|
||||
flushimage(display, 1);
|
||||
switch(alt(alts)){
|
||||
case MResize:
|
||||
if(getwindow(display, Refnone) < 0)
|
||||
|
@ -473,8 +479,6 @@ mousethread(void *v)
|
|||
draw(screen, screen->r, display->white, nil, ZP);
|
||||
scrlresize();
|
||||
rowresize(&row, screen->clipr);
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
break;
|
||||
case MPlumb:
|
||||
if(strcmp(pm->type, "text") == 0){
|
||||
|
@ -484,10 +488,10 @@ mousethread(void *v)
|
|||
else if(strcmp(act, "showdata")==0)
|
||||
plumbshow(pm);
|
||||
}
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
plumbfree(pm);
|
||||
break;
|
||||
case MWarnings:
|
||||
break;
|
||||
case MMouse:
|
||||
/*
|
||||
* Make a copy so decisions are consistent; mousectl changes
|
||||
|
@ -570,8 +574,6 @@ mousethread(void *v)
|
|||
goto Continue;
|
||||
}
|
||||
Continue:
|
||||
flushwarnings(0);
|
||||
flushimage(display, 1);
|
||||
qunlock(&row.lk);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -543,5 +543,6 @@ Channel *mouseexit1; /* chan(int) */
|
|||
Channel *cexit; /* chan(int) */
|
||||
Channel *cerr; /* chan(char*) */
|
||||
Channel *cedit; /* chan(int) */
|
||||
Channel *cwarn; /* chan(void*)[1] (really chan(unit)[1]) */
|
||||
|
||||
#define STACK 32768
|
||||
|
|
|
@ -268,7 +268,7 @@ D_cmd(Text *t, Cmd *cp)
|
|||
runemove(n, dir.r, dir.nr);
|
||||
n[dir.nr] = '/';
|
||||
runemove(n+dir.nr+1, r, nn);
|
||||
rs = cleanrname((Runestr){n, dir.nr+1+nn});
|
||||
rs = cleanrname(runestr(n, dir.nr+1+nn));
|
||||
}
|
||||
w = lookfile(rs.r, rs.nr);
|
||||
if(w == nil){
|
||||
|
|
|
@ -25,6 +25,7 @@ void fontx(Text*, Text*, Text*, int, int, Rune*, int);
|
|||
void get(Text*, Text*, Text*, int, int, Rune*, int);
|
||||
void id(Text*, Text*, Text*, int, int, Rune*, int);
|
||||
void incl(Text*, Text*, Text*, int, int, Rune*, int);
|
||||
void indent(Text*, Text*, Text*, int, int, Rune*, int);
|
||||
void xkill(Text*, Text*, Text*, int, int, Rune*, int);
|
||||
void local(Text*, Text*, Text*, int, int, Rune*, int);
|
||||
void look(Text*, Text*, Text*, int, int, Rune*, int);
|
||||
|
@ -58,6 +59,7 @@ static Rune LFont[] = { 'F', 'o', 'n', 't', 0 };
|
|||
static Rune LGet[] = { 'G', 'e', 't', 0 };
|
||||
static Rune LID[] = { 'I', 'D', 0 };
|
||||
static Rune LIncl[] = { 'I', 'n', 'c', 'l', 0 };
|
||||
static Rune LIndent[] = { 'I', 'n', 'd', 'e', 'n', 't', 0 };
|
||||
static Rune LKill[] = { 'K', 'i', 'l', 'l', 0 };
|
||||
static Rune LLoad[] = { 'L', 'o', 'a', 'd', 0 };
|
||||
static Rune LLocal[] = { 'L', 'o', 'c', 'a', 'l', 0 };
|
||||
|
@ -87,6 +89,7 @@ Exectab exectab[] = {
|
|||
{ LGet, get, FALSE, TRUE, XXX },
|
||||
{ LID, id, FALSE, XXX, XXX },
|
||||
{ LIncl, incl, FALSE, XXX, XXX },
|
||||
{ LIndent, indent, FALSE, XXX, XXX },
|
||||
{ LKill, xkill, FALSE, XXX, XXX },
|
||||
{ LLoad, dump, FALSE, FALSE, XXX },
|
||||
{ LLocal, local, FALSE, XXX, XXX },
|
||||
|
@ -1443,7 +1446,6 @@ runproc(void *argvp)
|
|||
goto Fail;
|
||||
|
||||
Hard:
|
||||
|
||||
/*
|
||||
* ugly: set path = (. $cputype /bin)
|
||||
* should honor $path if unusual.
|
||||
|
|
|
@ -69,6 +69,7 @@ Rune* bytetorune(char*, int*);
|
|||
void fsysinit(void);
|
||||
Mntdir* fsysmount(Rune*, int, Rune**, int);
|
||||
void fsysdelid(Mntdir*);
|
||||
void fsysincid(Mntdir*);
|
||||
Xfid* respond(Xfid*, Fcall*, char*);
|
||||
int rxcompile(Rune*);
|
||||
int rgetc(void*, uint);
|
||||
|
@ -86,9 +87,11 @@ int expand(Text*, uint, uint, Expand*);
|
|||
Rune* skipbl(Rune*, int, int*);
|
||||
Rune* findbl(Rune*, int, int*);
|
||||
char* edittext(Window*, int, Rune*, int);
|
||||
void flushwarnings(int);
|
||||
void flushwarnings(void);
|
||||
void startplumbing(void);
|
||||
|
||||
Runestr runestr(Rune*, uint);
|
||||
|
||||
#define runemalloc(a) (Rune*)emalloc((a)*sizeof(Rune))
|
||||
#define runerealloc(a, b) (Rune*)erealloc((a), (b)*sizeof(Rune))
|
||||
#define runemove(a, b, c) memmove((a), (b), (c)*sizeof(Rune))
|
||||
|
|
|
@ -37,22 +37,25 @@ static Xfid* fsysremove(Xfid*, Fid*);
|
|||
static Xfid* fsysstat(Xfid*, Fid*);
|
||||
static Xfid* fsyswstat(Xfid*, Fid*);
|
||||
|
||||
Xfid* (*fcall[Tmax])(Xfid*, Fid*) =
|
||||
Xfid* (*fcall[Tmax])(Xfid*, Fid*);
|
||||
|
||||
static void
|
||||
initfcall(void)
|
||||
{
|
||||
[Tflush] = fsysflush,
|
||||
[Tversion] = fsysversion,
|
||||
[Tauth] = fsysauth,
|
||||
[Tattach] = fsysattach,
|
||||
[Twalk] = fsyswalk,
|
||||
[Topen] = fsysopen,
|
||||
[Tcreate] = fsyscreate,
|
||||
[Tread] = fsysread,
|
||||
[Twrite] = fsyswrite,
|
||||
[Tclunk] = fsysclunk,
|
||||
[Tremove]= fsysremove,
|
||||
[Tstat] = fsysstat,
|
||||
[Twstat] = fsyswstat,
|
||||
};
|
||||
fcall[Tflush] = fsysflush;
|
||||
fcall[Tversion] = fsysversion;
|
||||
fcall[Tauth] = fsysauth;
|
||||
fcall[Tattach] = fsysattach;
|
||||
fcall[Twalk] = fsyswalk;
|
||||
fcall[Topen] = fsysopen;
|
||||
fcall[Tcreate] = fsyscreate;
|
||||
fcall[Tread] = fsysread;
|
||||
fcall[Twrite] = fsyswrite;
|
||||
fcall[Tclunk] = fsysclunk;
|
||||
fcall[Tremove]= fsysremove;
|
||||
fcall[Tstat] = fsysstat;
|
||||
fcall[Twstat] = fsyswstat;
|
||||
}
|
||||
|
||||
char Eperm[] = "permission denied";
|
||||
char Eexist[] = "file does not exist";
|
||||
|
@ -113,6 +116,7 @@ fsysinit(void)
|
|||
int p[2];
|
||||
char *u;
|
||||
|
||||
initfcall();
|
||||
if(pipe(p) < 0)
|
||||
error("can't create pipe");
|
||||
if(post9pservice(p[0], "acme") < 0)
|
||||
|
@ -186,6 +190,14 @@ fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl)
|
|||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
fsysincid(Mntdir *m)
|
||||
{
|
||||
qlock(&mnt.lk);
|
||||
m->ref++;
|
||||
qunlock(&mnt.lk);
|
||||
}
|
||||
|
||||
void
|
||||
fsysdelid(Mntdir *idm)
|
||||
{
|
||||
|
@ -331,7 +343,7 @@ fsysattach(Xfid *x, Fid *f)
|
|||
m->ref++;
|
||||
break;
|
||||
}
|
||||
if(m == nil){
|
||||
if(m == nil && x->fcall.aname[0]){
|
||||
snprint(buf, sizeof buf, "unknown id '%s' in attach", x->fcall.aname);
|
||||
sendp(cerr, estrdup(buf));
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ plumbshow(Plumbmsg *m)
|
|||
}
|
||||
cvttorunes(name, strlen(name), rb, &nb, &nr, nil);
|
||||
free(p);
|
||||
rs = cleanrname((Runestr){rb, nr});
|
||||
rs = cleanrname(runestr(rb, nr));
|
||||
winsetname(w, rs.r, rs.nr);
|
||||
r = runemalloc(m->ndata);
|
||||
cvttorunes(m->data, m->ndata, r, &nb, &nr, nil);
|
||||
|
@ -385,13 +385,13 @@ includefile(Rune *dir, Rune *file, int nfile)
|
|||
n = access(a, 0);
|
||||
free(a);
|
||||
if(n < 0)
|
||||
return (Runestr){nil, 0};
|
||||
return runestr(nil, 0);
|
||||
r = runemalloc(m+1+nfile);
|
||||
runemove(r, dir, m);
|
||||
runemove(r+m, Lslash, 1);
|
||||
runemove(r+m+1, file, nfile);
|
||||
free(file);
|
||||
return cleanrname((Runestr){r, m+1+nfile});
|
||||
return cleanrname(runestr(r, m+1+nfile));
|
||||
}
|
||||
|
||||
static Rune *objdir;
|
||||
|
@ -442,7 +442,7 @@ includename(Text *t, Rune *r, int n)
|
|||
return file;
|
||||
|
||||
Rescue:
|
||||
return (Runestr){r, n};
|
||||
return runestr(r, n);
|
||||
}
|
||||
|
||||
Runestr
|
||||
|
@ -475,11 +475,11 @@ dirname(Text *t, Rune *r, int n)
|
|||
goto Rescue;
|
||||
runemove(b+slash+1, r, n);
|
||||
free(r);
|
||||
return cleanrname((Runestr){b, slash+1+n});
|
||||
return cleanrname(runestr(b, slash+1+n));
|
||||
|
||||
Rescue:
|
||||
free(b);
|
||||
tmp = (Runestr){r, n};
|
||||
tmp = runestr(r, n);
|
||||
if(r)
|
||||
return cleanrname(tmp);
|
||||
return tmp;
|
||||
|
|
|
@ -578,7 +578,7 @@ textcomplete(Text *t)
|
|||
path[i] = textreadc(t, q++);
|
||||
/* is path rooted? if not, we need to make it relative to window path */
|
||||
if(npath>0 && path[0]=='/')
|
||||
dir = (Runestr){path, npath};
|
||||
dir = runestr(path, npath);
|
||||
else{
|
||||
dir = dirname(t, nil, 0);
|
||||
if(dir.nr + 1 + npath > nelem(tmp)){
|
||||
|
|
|
@ -14,6 +14,16 @@
|
|||
static Point prevmouse;
|
||||
static Window *mousew;
|
||||
|
||||
Runestr
|
||||
runestr(Rune *r, uint n)
|
||||
{
|
||||
Runestr rs;
|
||||
|
||||
rs.r = r;
|
||||
rs.nr = n;
|
||||
return rs;
|
||||
}
|
||||
|
||||
void
|
||||
cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
|
||||
{
|
||||
|
@ -133,12 +143,17 @@ addwarningtext(Mntdir *md, Rune *r, int nr)
|
|||
}
|
||||
warn = emalloc(sizeof(Warning));
|
||||
warn->next = warnings;
|
||||
warn->md = md;
|
||||
if(md)
|
||||
fsysincid(md);
|
||||
warnings = warn;
|
||||
bufinsert(&warn->buf, 0, r, nr);
|
||||
nbsendp(cwarn, 0);
|
||||
}
|
||||
|
||||
/* called while row is locked */
|
||||
void
|
||||
flushwarnings(int dolock)
|
||||
flushwarnings(void)
|
||||
{
|
||||
Warning *warn, *next;
|
||||
Window *w;
|
||||
|
@ -146,8 +161,6 @@ flushwarnings(int dolock)
|
|||
int owner, nr, q0, n;
|
||||
Rune *r;
|
||||
|
||||
if(dolock)
|
||||
qlock(&row.lk);
|
||||
if(row.ncol == 0){ /* really early error */
|
||||
rowinit(&row, screen->clipr);
|
||||
rowadd(&row, nil, -1);
|
||||
|
@ -189,11 +202,11 @@ flushwarnings(int dolock)
|
|||
winunlock(w);
|
||||
bufclose(&warn->buf);
|
||||
next = warn->next;
|
||||
if(warn->md)
|
||||
fsysdelid(warn->md);
|
||||
free(warn);
|
||||
}
|
||||
warnings = nil;
|
||||
if(dolock)
|
||||
qunlock(&row.lk);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -543,7 +543,6 @@ xfidwrite(Xfid *x)
|
|||
}
|
||||
if(w)
|
||||
winunlock(w);
|
||||
flushwarnings(1);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -814,7 +813,6 @@ xfideventwrite(Xfid *x, Window *w)
|
|||
qunlock(&row.lk);
|
||||
goto Rescue;
|
||||
}
|
||||
flushwarnings(0);
|
||||
qunlock(&row.lk);
|
||||
|
||||
}
|
||||
|
@ -1032,7 +1030,6 @@ xfidindexread(Xfid *x)
|
|||
b[n++] = '\n';
|
||||
}
|
||||
}
|
||||
flushwarnings(0);
|
||||
qunlock(&row.lk);
|
||||
off = x->fcall.offset;
|
||||
cnt = x->fcall.count;
|
||||
|
|
|
@ -119,6 +119,8 @@ main(int argc, char **argv)
|
|||
line = malloc(strlen(p)+5);
|
||||
sprint(line, "/%s/P\n", p);
|
||||
}
|
||||
dict->path = unsharp(dict->path);
|
||||
dict->indexpath = unsharp(dict->indexpath);
|
||||
bdict = Bopen(dict->path, OREAD);
|
||||
if(!bdict) {
|
||||
err("can't open dictionary %s", dict->path);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#define stdout bstdout
|
||||
|
||||
char mode; /* '\0', 'e', 'f', 'h' */
|
||||
char bflag; /* ignore multiple and trailing blanks */
|
||||
char rflag; /* recurse down directory trees */
|
||||
|
|
|
@ -26,6 +26,8 @@ void
|
|||
done(int status)
|
||||
{
|
||||
rmtmpfiles();
|
||||
Bflush(&stdout);
|
||||
Bterm(&stdout);
|
||||
switch(status)
|
||||
{
|
||||
case 0:
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#define index findex
|
||||
char choice[2048];
|
||||
char index[] = "/sys/games/lib/fortunes.index";
|
||||
char fortunes[] = "/sys/games/lib/fortunes";
|
||||
char *index = "#9/lib/fortunes.index";
|
||||
char *fortunes = "#9/lib/fortunes";
|
||||
|
||||
#define lrand rand
|
||||
|
||||
|
@ -21,6 +21,9 @@ main(int argc, char *argv[])
|
|||
Dir *fbuf, *ixbuf;
|
||||
Biobuf *f, g;
|
||||
|
||||
index = unsharp(index);
|
||||
fortunes = unsharp(index);
|
||||
|
||||
newindex = 0;
|
||||
oldindex = 0;
|
||||
ix = offs = 0;
|
||||
|
@ -55,6 +58,7 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
if(oldindex){
|
||||
srand(getpid());
|
||||
seek(ix, lrand()%(ixbuf->length/sizeof(offs))*sizeof(offs), 0);
|
||||
read(ix, off, sizeof(off));
|
||||
Bseek(f, off[0]|(off[1]<<8)|(off[2]<<16)|(off[3]<<24), 0);
|
||||
|
|
277
src/cmd/grep/comp.c
Normal file
277
src/cmd/grep/comp.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
#include "grep.h"
|
||||
|
||||
/*
|
||||
* incremental compiler.
|
||||
* add the branch c to the
|
||||
* state s.
|
||||
*/
|
||||
void
|
||||
increment(State *s, int c)
|
||||
{
|
||||
int i;
|
||||
State *t, **tt;
|
||||
Re *re1, *re2;
|
||||
|
||||
nfollow = 0;
|
||||
gen++;
|
||||
matched = 0;
|
||||
for(i=0; i<s->count; i++)
|
||||
fol1(s->re[i], c);
|
||||
qsort(follow, nfollow, sizeof(*follow), fcmp);
|
||||
for(tt=&state0; t = *tt;) {
|
||||
if(t->count > nfollow) {
|
||||
tt = &t->linkleft;
|
||||
goto cont;
|
||||
}
|
||||
if(t->count < nfollow) {
|
||||
tt = &t->linkright;
|
||||
goto cont;
|
||||
}
|
||||
for(i=0; i<nfollow; i++) {
|
||||
re1 = t->re[i];
|
||||
re2 = follow[i];
|
||||
if(re1 > re2) {
|
||||
tt = &t->linkleft;
|
||||
goto cont;
|
||||
}
|
||||
if(re1 < re2) {
|
||||
tt = &t->linkright;
|
||||
goto cont;
|
||||
}
|
||||
}
|
||||
if(!!matched && !t->match) {
|
||||
tt = &t->linkleft;
|
||||
goto cont;
|
||||
}
|
||||
if(!matched && !!t->match) {
|
||||
tt = &t->linkright;
|
||||
goto cont;
|
||||
}
|
||||
s->next[c] = t;
|
||||
return;
|
||||
cont:;
|
||||
}
|
||||
|
||||
t = sal(nfollow);
|
||||
*tt = t;
|
||||
for(i=0; i<nfollow; i++) {
|
||||
re1 = follow[i];
|
||||
t->re[i] = re1;
|
||||
}
|
||||
s->next[c] = t;
|
||||
t->match = matched;
|
||||
}
|
||||
|
||||
int
|
||||
fcmp(const void *va, const void *vb)
|
||||
{
|
||||
Re **aa, **bb;
|
||||
Re *a, *b;
|
||||
|
||||
aa = (Re**)va;
|
||||
bb = (Re**)vb;
|
||||
a = *aa;
|
||||
b = *bb;
|
||||
if(a > b)
|
||||
return 1;
|
||||
if(a < b)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fol1(Re *r, int c)
|
||||
{
|
||||
Re *r1;
|
||||
|
||||
loop:
|
||||
if(r->gen == gen)
|
||||
return;
|
||||
if(nfollow >= maxfollow)
|
||||
error("nfollow");
|
||||
r->gen = gen;
|
||||
switch(r->type) {
|
||||
default:
|
||||
error("fol1");
|
||||
|
||||
case Tcase:
|
||||
if(c >= 0 && c < 256)
|
||||
if(r1 = r->cases[c])
|
||||
follow[nfollow++] = r1;
|
||||
if(r = r->next)
|
||||
goto loop;
|
||||
break;
|
||||
|
||||
case Talt:
|
||||
case Tor:
|
||||
fol1(r->alt, c);
|
||||
r = r->next;
|
||||
goto loop;
|
||||
|
||||
case Tbegin:
|
||||
if(c == '\n' || c == Cbegin)
|
||||
follow[nfollow++] = r->next;
|
||||
break;
|
||||
|
||||
case Tend:
|
||||
if(c == '\n')
|
||||
matched = 1;
|
||||
break;
|
||||
|
||||
case Tclass:
|
||||
if(c >= r->lo && c <= r->hi)
|
||||
follow[nfollow++] = r->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Rune tab1[] =
|
||||
{
|
||||
0x007f,
|
||||
0x07ff,
|
||||
};
|
||||
Rune tab2[] =
|
||||
{
|
||||
0x003f,
|
||||
0x0fff,
|
||||
};
|
||||
|
||||
Re2
|
||||
rclass(Rune p0, Rune p1)
|
||||
{
|
||||
char xc0[6], xc1[6];
|
||||
int i, n, m;
|
||||
Re2 x;
|
||||
|
||||
if(p0 > p1)
|
||||
return re2char(0xff, 0xff); // no match
|
||||
|
||||
/*
|
||||
* bust range into same length
|
||||
* character sequences
|
||||
*/
|
||||
for(i=0; i<nelem(tab1); i++) {
|
||||
m = tab1[i];
|
||||
if(p0 <= m && p1 > m)
|
||||
return re2or(rclass(p0, m), rclass(m+1, p1));
|
||||
}
|
||||
|
||||
/*
|
||||
* bust range into part of a single page
|
||||
* or into full pages
|
||||
*/
|
||||
for(i=0; i<nelem(tab2); i++) {
|
||||
m = tab2[i];
|
||||
if((p0 & ~m) != (p1 & ~m)) {
|
||||
if((p0 & m) != 0)
|
||||
return re2or(rclass(p0, p0|m), rclass((p0|m)+1, p1));
|
||||
if((p1 & m) != m)
|
||||
return re2or(rclass(p0, (p1&~m)-1), rclass(p1&~m, p1));
|
||||
}
|
||||
}
|
||||
|
||||
n = runetochar(xc0, &p0);
|
||||
i = runetochar(xc1, &p1);
|
||||
if(i != n)
|
||||
error("length");
|
||||
|
||||
x = re2char(xc0[0], xc1[0]);
|
||||
for(i=1; i<n; i++)
|
||||
x = re2cat(x, re2char(xc0[i], xc1[i]));
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
pcmp(const void *va, const void *vb)
|
||||
{
|
||||
int n;
|
||||
Rune *a, *b;
|
||||
|
||||
a = (Rune*)va;
|
||||
b = (Rune*)vb;
|
||||
|
||||
n = a[0] - b[0];
|
||||
if(n)
|
||||
return n;
|
||||
return a[1] - b[1];
|
||||
}
|
||||
|
||||
/*
|
||||
* convert character chass into
|
||||
* run-pair ranges of matches.
|
||||
* this is 10646/utf specific and
|
||||
* needs to be changed for some
|
||||
* other input character set.
|
||||
* this is the key to a fast
|
||||
* regular search of characters
|
||||
* by looking at sequential bytes.
|
||||
*/
|
||||
Re2
|
||||
re2class(char *s)
|
||||
{
|
||||
Rune pairs[200], *p, *q, ov;
|
||||
int nc;
|
||||
Re2 x;
|
||||
|
||||
nc = 0;
|
||||
if(*s == '^') {
|
||||
nc = 1;
|
||||
s++;
|
||||
}
|
||||
|
||||
p = pairs;
|
||||
s += chartorune(p, s);
|
||||
for(;;) {
|
||||
if(*p == '\\')
|
||||
s += chartorune(p, s);
|
||||
if(*p == 0)
|
||||
break;
|
||||
p[1] = *p;
|
||||
p += 2;
|
||||
s += chartorune(p, s);
|
||||
if(*p != '-')
|
||||
continue;
|
||||
s += chartorune(p, s);
|
||||
if(*p == '\\')
|
||||
s += chartorune(p, s);
|
||||
if(*p == 0)
|
||||
break;
|
||||
p[-1] = *p;
|
||||
s += chartorune(p, s);
|
||||
}
|
||||
*p = 0;
|
||||
qsort(pairs, (p-pairs)/2, 2*sizeof(*pairs), pcmp);
|
||||
|
||||
q = pairs;
|
||||
for(p=pairs+2; *p; p+=2) {
|
||||
if(p[0] > p[1])
|
||||
continue;
|
||||
if(p[0] > q[1] || p[1] < q[0]) {
|
||||
q[2] = p[0];
|
||||
q[3] = p[1];
|
||||
q += 2;
|
||||
continue;
|
||||
}
|
||||
if(p[0] < q[0])
|
||||
q[0] = p[0];
|
||||
if(p[1] > q[1])
|
||||
q[1] = p[1];
|
||||
}
|
||||
q[2] = 0;
|
||||
|
||||
p = pairs;
|
||||
if(nc) {
|
||||
x = rclass(0, p[0]-1);
|
||||
ov = p[1]+1;
|
||||
for(p+=2; *p; p+=2) {
|
||||
x = re2or(x, rclass(ov, p[0]-1));
|
||||
ov = p[1]+1;
|
||||
}
|
||||
x = re2or(x, rclass(ov, 0xffff));
|
||||
} else {
|
||||
x = rclass(p[0], p[1]);
|
||||
for(p+=2; *p; p+=2)
|
||||
x = re2or(x, rclass(p[0], p[1]));
|
||||
}
|
||||
return x;
|
||||
}
|
125
src/cmd/grep/grep.h
Normal file
125
src/cmd/grep/grep.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct Re Re;
|
||||
typedef struct Re2 Re2;
|
||||
typedef struct State State;
|
||||
|
||||
struct State
|
||||
{
|
||||
int count;
|
||||
int match;
|
||||
Re** re;
|
||||
State* linkleft;
|
||||
State* linkright;
|
||||
State* next[256];
|
||||
};
|
||||
struct Re2
|
||||
{
|
||||
Re* beg;
|
||||
Re* end;
|
||||
};
|
||||
struct Re
|
||||
{
|
||||
uchar type;
|
||||
ushort gen;
|
||||
union
|
||||
{
|
||||
Re* alt; /* Talt */
|
||||
Re** cases; /* case */
|
||||
struct /* class */
|
||||
{
|
||||
Rune lo;
|
||||
Rune hi;
|
||||
};
|
||||
Rune val; /* char */
|
||||
};
|
||||
Re* next;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Talt = 1,
|
||||
Tbegin,
|
||||
Tcase,
|
||||
Tclass,
|
||||
Tend,
|
||||
Tor,
|
||||
|
||||
Caselim = 7,
|
||||
Nhunk = 1<<16,
|
||||
Cbegin = 0x10000,
|
||||
Flshcnt = (1<<9)-1,
|
||||
|
||||
Cflag = 1<<0,
|
||||
Hflag = 1<<1,
|
||||
Iflag = 1<<2,
|
||||
Llflag = 1<<3,
|
||||
LLflag = 1<<4,
|
||||
Nflag = 1<<5,
|
||||
Sflag = 1<<6,
|
||||
Vflag = 1<<7,
|
||||
Bflag = 1<<8
|
||||
};
|
||||
|
||||
EXTERN union
|
||||
{
|
||||
char string[16*1024];
|
||||
struct
|
||||
{
|
||||
/*
|
||||
* if a line requires multiple reads, we keep shifting
|
||||
* buf down into pre and then do another read into
|
||||
* buf. so you'll get the last 16-32k of the matching line.
|
||||
* if pre were smaller than buf you'd get a suffix of the
|
||||
* line with a hole cut out.
|
||||
*/
|
||||
uchar pre[16*1024]; /* to save to previous '\n' */
|
||||
uchar buf[16*1024]; /* input buffer */
|
||||
};
|
||||
} u;
|
||||
|
||||
EXTERN char *filename;
|
||||
EXTERN Biobuf bout;
|
||||
EXTERN char flags[256];
|
||||
EXTERN Re** follow;
|
||||
EXTERN ushort gen;
|
||||
EXTERN char* input;
|
||||
EXTERN long lineno;
|
||||
EXTERN int literal;
|
||||
EXTERN int matched;
|
||||
EXTERN long maxfollow;
|
||||
EXTERN long nfollow;
|
||||
EXTERN int peekc;
|
||||
EXTERN Biobuf* rein;
|
||||
EXTERN State* state0;
|
||||
EXTERN Re2 topre;
|
||||
|
||||
extern Re* addcase(Re*);
|
||||
extern void appendnext(Re*, Re*);
|
||||
extern void error(char*);
|
||||
extern int fcmp(const void*, const void*); /* (Re**, Re**) */
|
||||
extern void fol1(Re*, int);
|
||||
extern int getrec(void);
|
||||
extern void increment(State*, int);
|
||||
#define initstate grepinitstate
|
||||
extern State* initstate(Re*);
|
||||
extern void* mal(int);
|
||||
extern void patchnext(Re*, Re*);
|
||||
extern Re* ral(int);
|
||||
extern Re2 re2cat(Re2, Re2);
|
||||
extern Re2 re2class(char*);
|
||||
extern Re2 re2or(Re2, Re2);
|
||||
extern Re2 re2char(int, int);
|
||||
extern Re2 re2star(Re2);
|
||||
extern State* sal(int);
|
||||
extern int search(char*, int);
|
||||
extern void str2top(char*);
|
||||
extern int yyparse(void);
|
||||
extern void reprint(char*, Re*);
|
||||
extern void yyerror(char*, ...);
|
226
src/cmd/grep/grep.y
Normal file
226
src/cmd/grep/grep.y
Normal file
|
@ -0,0 +1,226 @@
|
|||
%{
|
||||
#include "grep.h"
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
int val;
|
||||
char* str;
|
||||
Re2 re;
|
||||
}
|
||||
|
||||
%type <re> expr prog
|
||||
%type <re> expr0 expr1 expr2 expr3 expr4
|
||||
%token <str> LCLASS
|
||||
%token <val> LCHAR
|
||||
%token LLPAREN LRPAREN LALT LSTAR LPLUS LQUES
|
||||
%token LBEGIN LEND LDOT LBAD LNEWLINE
|
||||
%%
|
||||
|
||||
prog:
|
||||
expr newlines
|
||||
{
|
||||
$$.beg = ral(Tend);
|
||||
$$.end = $$.beg;
|
||||
$$ = re2cat(re2star(re2or(re2char(0x00, '\n'-1), re2char('\n'+1, 0xff))), $$);
|
||||
$$ = re2cat($1, $$);
|
||||
$$ = re2cat(re2star(re2char(0x00, 0xff)), $$);
|
||||
topre = $$;
|
||||
}
|
||||
|
||||
expr:
|
||||
expr0
|
||||
| expr newlines expr0
|
||||
{
|
||||
$$ = re2or($1, $3);
|
||||
}
|
||||
|
||||
expr0:
|
||||
expr1
|
||||
| LSTAR { literal = 1; } expr1
|
||||
{
|
||||
$$ = $3;
|
||||
}
|
||||
|
||||
expr1:
|
||||
expr2
|
||||
| expr1 LALT expr2
|
||||
{
|
||||
$$ = re2or($1, $3);
|
||||
}
|
||||
|
||||
expr2:
|
||||
expr3
|
||||
| expr2 expr3
|
||||
{
|
||||
$$ = re2cat($1, $2);
|
||||
}
|
||||
|
||||
expr3:
|
||||
expr4
|
||||
| expr3 LSTAR
|
||||
{
|
||||
$$ = re2star($1);
|
||||
}
|
||||
| expr3 LPLUS
|
||||
{
|
||||
$$.beg = ral(Talt);
|
||||
patchnext($1.end, $$.beg);
|
||||
$$.beg->alt = $1.beg;
|
||||
$$.end = $$.beg;
|
||||
$$.beg = $1.beg;
|
||||
}
|
||||
| expr3 LQUES
|
||||
{
|
||||
$$.beg = ral(Talt);
|
||||
$$.beg->alt = $1.beg;
|
||||
$$.end = $1.end;
|
||||
appendnext($$.end, $$.beg);
|
||||
}
|
||||
|
||||
expr4:
|
||||
LCHAR
|
||||
{
|
||||
$$.beg = ral(Tclass);
|
||||
$$.beg->lo = $1;
|
||||
$$.beg->hi = $1;
|
||||
$$.end = $$.beg;
|
||||
}
|
||||
| LBEGIN
|
||||
{
|
||||
$$.beg = ral(Tbegin);
|
||||
$$.end = $$.beg;
|
||||
}
|
||||
| LEND
|
||||
{
|
||||
$$.beg = ral(Tend);
|
||||
$$.end = $$.beg;
|
||||
}
|
||||
| LDOT
|
||||
{
|
||||
$$ = re2class("^\n");
|
||||
}
|
||||
| LCLASS
|
||||
{
|
||||
$$ = re2class($1);
|
||||
}
|
||||
| LLPAREN expr1 LRPAREN
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
newlines:
|
||||
LNEWLINE
|
||||
| newlines LNEWLINE
|
||||
%%
|
||||
|
||||
void
|
||||
yyerror(char *e, ...)
|
||||
{
|
||||
if(filename)
|
||||
fprint(2, "grep: %s:%ld: %s\n", filename, lineno, e);
|
||||
else
|
||||
fprint(2, "grep: %s\n", e);
|
||||
exits("syntax");
|
||||
}
|
||||
|
||||
long
|
||||
yylex(void)
|
||||
{
|
||||
char *q, *eq;
|
||||
int c, s;
|
||||
|
||||
if(peekc) {
|
||||
s = peekc;
|
||||
peekc = 0;
|
||||
return s;
|
||||
}
|
||||
c = getrec();
|
||||
if(literal) {
|
||||
if(c != 0 && c != '\n') {
|
||||
yylval.val = c;
|
||||
return LCHAR;
|
||||
}
|
||||
literal = 0;
|
||||
}
|
||||
switch(c) {
|
||||
default:
|
||||
yylval.val = c;
|
||||
s = LCHAR;
|
||||
break;
|
||||
case '\\':
|
||||
c = getrec();
|
||||
yylval.val = c;
|
||||
s = LCHAR;
|
||||
if(c == '\n')
|
||||
s = LNEWLINE;
|
||||
break;
|
||||
case '[':
|
||||
goto getclass;
|
||||
case '(':
|
||||
s = LLPAREN;
|
||||
break;
|
||||
case ')':
|
||||
s = LRPAREN;
|
||||
break;
|
||||
case '|':
|
||||
s = LALT;
|
||||
break;
|
||||
case '*':
|
||||
s = LSTAR;
|
||||
break;
|
||||
case '+':
|
||||
s = LPLUS;
|
||||
break;
|
||||
case '?':
|
||||
s = LQUES;
|
||||
break;
|
||||
case '^':
|
||||
s = LBEGIN;
|
||||
break;
|
||||
case '$':
|
||||
s = LEND;
|
||||
break;
|
||||
case '.':
|
||||
s = LDOT;
|
||||
break;
|
||||
case 0:
|
||||
peekc = -1;
|
||||
case '\n':
|
||||
s = LNEWLINE;
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
|
||||
getclass:
|
||||
q = u.string;
|
||||
eq = q + nelem(u.string) - 5;
|
||||
c = getrec();
|
||||
if(c == '^') {
|
||||
q[0] = '^';
|
||||
q[1] = '\n';
|
||||
q[2] = '-';
|
||||
q[3] = '\n';
|
||||
q += 4;
|
||||
c = getrec();
|
||||
}
|
||||
for(;;) {
|
||||
if(q >= eq)
|
||||
error("class too long");
|
||||
if(c == ']' || c == 0)
|
||||
break;
|
||||
if(c == '\\') {
|
||||
*q++ = c;
|
||||
c = getrec();
|
||||
if(c == 0)
|
||||
break;
|
||||
}
|
||||
*q++ = c;
|
||||
c = getrec();
|
||||
}
|
||||
*q = 0;
|
||||
if(c == 0)
|
||||
return LBAD;
|
||||
yylval.str = u.string;
|
||||
return LCLASS;
|
||||
}
|
260
src/cmd/grep/main.c
Normal file
260
src/cmd/grep/main.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
#define EXTERN
|
||||
#include "grep.h"
|
||||
|
||||
char *validflags = "bchiLlnsv";
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: grep [-%s] [-f file] [-e expr] [file ...]\n", validflags);
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, status;
|
||||
|
||||
ARGBEGIN {
|
||||
default:
|
||||
if(utfrune(validflags, ARGC()) == nil)
|
||||
usage();
|
||||
flags[ARGC()]++;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
flags['e']++;
|
||||
lineno = 0;
|
||||
str2top(ARGF());
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
flags['f']++;
|
||||
filename = ARGF();
|
||||
rein = Bopen(filename, OREAD);
|
||||
if(rein == 0) {
|
||||
fprint(2, "grep: can't open %s: %r\n", filename);
|
||||
exits("open");
|
||||
}
|
||||
lineno = 1;
|
||||
str2top(filename);
|
||||
break;
|
||||
} ARGEND
|
||||
|
||||
if(flags['f'] == 0 && flags['e'] == 0) {
|
||||
if(argc <= 0)
|
||||
usage();
|
||||
str2top(argv[0]);
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
follow = mal(maxfollow*sizeof(*follow));
|
||||
state0 = initstate(topre.beg);
|
||||
|
||||
Binit(&bout, 1, OWRITE);
|
||||
switch(argc) {
|
||||
case 0:
|
||||
status = search(0, 0);
|
||||
break;
|
||||
case 1:
|
||||
status = search(argv[0], 0);
|
||||
break;
|
||||
default:
|
||||
status = 0;
|
||||
for(i=0; i<argc; i++)
|
||||
status |= search(argv[i], Hflag);
|
||||
break;
|
||||
}
|
||||
if(status)
|
||||
exits(0);
|
||||
exits("no matches");
|
||||
}
|
||||
|
||||
int
|
||||
search(char *file, int flag)
|
||||
{
|
||||
State *s, *ns;
|
||||
int c, fid, eof, nl, empty;
|
||||
long count, lineno, n;
|
||||
uchar *elp, *lp, *bol;
|
||||
|
||||
if(file == 0) {
|
||||
file = "stdin";
|
||||
fid = 0;
|
||||
flag |= Bflag;
|
||||
} else
|
||||
fid = open(file, OREAD);
|
||||
|
||||
if(fid < 0) {
|
||||
fprint(2, "grep: can't open %s: %r\n", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(flags['b'])
|
||||
flag ^= Bflag; /* dont buffer output */
|
||||
if(flags['c'])
|
||||
flag |= Cflag; /* count */
|
||||
if(flags['h'])
|
||||
flag &= ~Hflag; /* do not print file name in output */
|
||||
if(flags['i'])
|
||||
flag |= Iflag; /* fold upper-lower */
|
||||
if(flags['l'])
|
||||
flag |= Llflag; /* print only name of file if any match */
|
||||
if(flags['L'])
|
||||
flag |= LLflag; /* print only name of file if any non match */
|
||||
if(flags['n'])
|
||||
flag |= Nflag; /* count only */
|
||||
if(flags['s'])
|
||||
flag |= Sflag; /* status only */
|
||||
if(flags['v'])
|
||||
flag |= Vflag; /* inverse match */
|
||||
|
||||
s = state0;
|
||||
lineno = 0;
|
||||
count = 0;
|
||||
eof = 0;
|
||||
empty = 1;
|
||||
nl = 0;
|
||||
lp = u.buf;
|
||||
bol = lp;
|
||||
|
||||
loop0:
|
||||
n = lp-bol;
|
||||
if(n > sizeof(u.pre))
|
||||
n = sizeof(u.pre);
|
||||
memmove(u.buf-n, bol, n);
|
||||
bol = u.buf-n;
|
||||
n = read(fid, u.buf, sizeof(u.buf));
|
||||
/* if file has no final newline, simulate one to emit matches to last line */
|
||||
if(n > 0) {
|
||||
empty = 0;
|
||||
nl = u.buf[n-1]=='\n';
|
||||
} else {
|
||||
if(n < 0){
|
||||
fprint(2, "grep: read error on %s: %r\n", file);
|
||||
return count != 0;
|
||||
}
|
||||
if(!eof && !nl && !empty) {
|
||||
u.buf[0] = '\n';
|
||||
n = 1;
|
||||
eof = 1;
|
||||
}
|
||||
}
|
||||
if(n <= 0) {
|
||||
close(fid);
|
||||
if(flag & Cflag) {
|
||||
if(flag & Hflag)
|
||||
Bprint(&bout, "%s:", file);
|
||||
Bprint(&bout, "%ld\n", count);
|
||||
}
|
||||
if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
|
||||
Bprint(&bout, "%s\n", file);
|
||||
Bflush(&bout);
|
||||
return count != 0;
|
||||
}
|
||||
lp = u.buf;
|
||||
elp = lp+n;
|
||||
if(flag & Iflag)
|
||||
goto loopi;
|
||||
|
||||
/*
|
||||
* normal character loop
|
||||
*/
|
||||
loop:
|
||||
c = *lp;
|
||||
ns = s->next[c];
|
||||
if(ns == 0) {
|
||||
increment(s, c);
|
||||
goto loop;
|
||||
}
|
||||
// if(flags['2'])
|
||||
// if(s->match)
|
||||
// print("%d: %.2x**\n", s, c);
|
||||
// else
|
||||
// print("%d: %.2x\n", s, c);
|
||||
lp++;
|
||||
s = ns;
|
||||
if(c == '\n') {
|
||||
lineno++;
|
||||
if(!!s->match == !(flag&Vflag)) {
|
||||
count++;
|
||||
if(flag & (Cflag|Sflag|Llflag|LLflag))
|
||||
goto cont;
|
||||
if(flag & Hflag)
|
||||
Bprint(&bout, "%s:", file);
|
||||
if(flag & Nflag)
|
||||
Bprint(&bout, "%ld: ", lineno);
|
||||
/* suppress extra newline at EOF unless we are labeling matches with file name */
|
||||
Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
|
||||
if(flag & Bflag)
|
||||
Bflush(&bout);
|
||||
}
|
||||
if((lineno & Flshcnt) == 0)
|
||||
Bflush(&bout);
|
||||
cont:
|
||||
bol = lp;
|
||||
}
|
||||
if(lp != elp)
|
||||
goto loop;
|
||||
goto loop0;
|
||||
|
||||
/*
|
||||
* character loop for -i flag
|
||||
* for speed
|
||||
*/
|
||||
loopi:
|
||||
c = *lp;
|
||||
if(c >= 'A' && c <= 'Z')
|
||||
c += 'a'-'A';
|
||||
ns = s->next[c];
|
||||
if(ns == 0) {
|
||||
increment(s, c);
|
||||
goto loopi;
|
||||
}
|
||||
lp++;
|
||||
s = ns;
|
||||
if(c == '\n') {
|
||||
lineno++;
|
||||
if(!!s->match == !(flag&Vflag)) {
|
||||
count++;
|
||||
if(flag & (Cflag|Sflag|Llflag|LLflag))
|
||||
goto conti;
|
||||
if(flag & Hflag)
|
||||
Bprint(&bout, "%s:", file);
|
||||
if(flag & Nflag)
|
||||
Bprint(&bout, "%ld: ", lineno);
|
||||
/* suppress extra newline at EOF unless we are labeling matches with file name */
|
||||
Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
|
||||
if(flag & Bflag)
|
||||
Bflush(&bout);
|
||||
}
|
||||
if((lineno & Flshcnt) == 0)
|
||||
Bflush(&bout);
|
||||
conti:
|
||||
bol = lp;
|
||||
}
|
||||
if(lp != elp)
|
||||
goto loopi;
|
||||
goto loop0;
|
||||
}
|
||||
|
||||
State*
|
||||
initstate(Re *r)
|
||||
{
|
||||
State *s;
|
||||
int i;
|
||||
|
||||
addcase(r);
|
||||
if(flags['1'])
|
||||
reprint("r", r);
|
||||
nfollow = 0;
|
||||
gen++;
|
||||
fol1(r, Cbegin);
|
||||
follow[nfollow++] = r;
|
||||
qsort(follow, nfollow, sizeof(*follow), fcmp);
|
||||
|
||||
s = sal(nfollow);
|
||||
for(i=0; i<nfollow; i++)
|
||||
s->re[i] = follow[i];
|
||||
return s;
|
||||
}
|
20
src/cmd/grep/mkfile
Normal file
20
src/cmd/grep/mkfile
Normal file
|
@ -0,0 +1,20 @@
|
|||
PLAN9=../../..
|
||||
<$PLAN9/src/mkhdr
|
||||
|
||||
# Calling this grep breaks a LOT. Like egrep on Linux.
|
||||
# And probably configure.
|
||||
|
||||
TARG=9grep
|
||||
HFILES=\
|
||||
grep.h\
|
||||
|
||||
OFILES=\
|
||||
y.tab.$O\
|
||||
main.$O\
|
||||
comp.$O\
|
||||
sub.$O\
|
||||
|
||||
YFILES=grep.y\
|
||||
|
||||
SHORTLIB=bio 9
|
||||
<$PLAN9/src/mkone
|
317
src/cmd/grep/sub.c
Normal file
317
src/cmd/grep/sub.c
Normal file
|
@ -0,0 +1,317 @@
|
|||
#include "grep.h"
|
||||
|
||||
void*
|
||||
mal(int n)
|
||||
{
|
||||
static char *s;
|
||||
static int m = 0;
|
||||
void *v;
|
||||
|
||||
n = (n+3) & ~3;
|
||||
if(m < n) {
|
||||
if(n > Nhunk) {
|
||||
v = sbrk(n);
|
||||
memset(v, 0, n);
|
||||
return v;
|
||||
}
|
||||
s = sbrk(Nhunk);
|
||||
m = Nhunk;
|
||||
}
|
||||
v = s;
|
||||
s += n;
|
||||
m -= n;
|
||||
memset(v, 0, n);
|
||||
return v;
|
||||
}
|
||||
|
||||
State*
|
||||
sal(int n)
|
||||
{
|
||||
State *s;
|
||||
|
||||
s = mal(sizeof(*s));
|
||||
// s->next = mal(256*sizeof(*s->next));
|
||||
s->count = n;
|
||||
s->re = mal(n*sizeof(*state0->re));
|
||||
return s;
|
||||
}
|
||||
|
||||
Re*
|
||||
ral(int type)
|
||||
{
|
||||
Re *r;
|
||||
|
||||
r = mal(sizeof(*r));
|
||||
r->type = type;
|
||||
maxfollow++;
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
error(char *s)
|
||||
{
|
||||
fprint(2, "grep: internal error: %s\n", s);
|
||||
exits(s);
|
||||
}
|
||||
|
||||
int
|
||||
countor(Re *r)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
loop:
|
||||
switch(r->type) {
|
||||
case Tor:
|
||||
n += countor(r->alt);
|
||||
r = r->next;
|
||||
goto loop;
|
||||
case Tclass:
|
||||
return n + r->hi - r->lo + 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
Re*
|
||||
oralloc(int t, Re *r, Re *b)
|
||||
{
|
||||
Re *a;
|
||||
|
||||
if(b == 0)
|
||||
return r;
|
||||
a = ral(t);
|
||||
a->alt = r;
|
||||
a->next = b;
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
case1(Re *c, Re *r)
|
||||
{
|
||||
int n;
|
||||
|
||||
loop:
|
||||
switch(r->type) {
|
||||
case Tor:
|
||||
case1(c, r->alt);
|
||||
r = r->next;
|
||||
goto loop;
|
||||
|
||||
case Tclass: /* add to character */
|
||||
for(n=r->lo; n<=r->hi; n++)
|
||||
c->cases[n] = oralloc(Tor, r->next, c->cases[n]);
|
||||
break;
|
||||
|
||||
default: /* add everything unknown to next */
|
||||
c->next = oralloc(Talt, r, c->next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Re*
|
||||
addcase(Re *r)
|
||||
{
|
||||
int i, n;
|
||||
Re *a;
|
||||
|
||||
if(r->gen == gen)
|
||||
return r;
|
||||
r->gen = gen;
|
||||
switch(r->type) {
|
||||
default:
|
||||
error("addcase");
|
||||
|
||||
case Tor:
|
||||
n = countor(r);
|
||||
if(n >= Caselim) {
|
||||
a = ral(Tcase);
|
||||
a->cases = mal(256*sizeof(*a->cases));
|
||||
case1(a, r);
|
||||
for(i=0; i<256; i++)
|
||||
if(a->cases[i]) {
|
||||
r = a->cases[i];
|
||||
if(countor(r) < n)
|
||||
a->cases[i] = addcase(r);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return r;
|
||||
|
||||
case Talt:
|
||||
r->next = addcase(r->next);
|
||||
r->alt = addcase(r->alt);
|
||||
return r;
|
||||
|
||||
case Tbegin:
|
||||
case Tend:
|
||||
case Tclass:
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
str2top(char *p)
|
||||
{
|
||||
Re2 oldtop;
|
||||
|
||||
oldtop = topre;
|
||||
input = p;
|
||||
topre.beg = 0;
|
||||
topre.end = 0;
|
||||
yyparse();
|
||||
gen++;
|
||||
if(topre.beg == 0)
|
||||
yyerror("syntax");
|
||||
if(oldtop.beg)
|
||||
topre = re2or(oldtop, topre);
|
||||
}
|
||||
|
||||
void
|
||||
appendnext(Re *a, Re *b)
|
||||
{
|
||||
Re *n;
|
||||
|
||||
while(n = a->next)
|
||||
a = n;
|
||||
a->next = b;
|
||||
}
|
||||
|
||||
void
|
||||
patchnext(Re *a, Re *b)
|
||||
{
|
||||
Re *n;
|
||||
|
||||
while(a) {
|
||||
n = a->next;
|
||||
a->next = b;
|
||||
a = n;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getrec(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if(flags['f']) {
|
||||
c = Bgetc(rein);
|
||||
if(c <= 0)
|
||||
return 0;
|
||||
} else
|
||||
c = *input++ & 0xff;
|
||||
if(flags['i'] && c >= 'A' && c <= 'Z')
|
||||
c += 'a'-'A';
|
||||
if(c == '\n')
|
||||
lineno++;
|
||||
return c;
|
||||
}
|
||||
|
||||
Re2
|
||||
re2cat(Re2 a, Re2 b)
|
||||
{
|
||||
Re2 c;
|
||||
|
||||
c.beg = a.beg;
|
||||
c.end = b.end;
|
||||
patchnext(a.end, b.beg);
|
||||
return c;
|
||||
}
|
||||
|
||||
Re2
|
||||
re2star(Re2 a)
|
||||
{
|
||||
Re2 c;
|
||||
|
||||
c.beg = ral(Talt);
|
||||
c.beg->alt = a.beg;
|
||||
patchnext(a.end, c.beg);
|
||||
c.end = c.beg;
|
||||
return c;
|
||||
}
|
||||
|
||||
Re2
|
||||
re2or(Re2 a, Re2 b)
|
||||
{
|
||||
Re2 c;
|
||||
|
||||
c.beg = ral(Tor);
|
||||
c.beg->alt = b.beg;
|
||||
c.beg->next = a.beg;
|
||||
c.end = b.end;
|
||||
appendnext(c.end, a.end);
|
||||
return c;
|
||||
}
|
||||
|
||||
Re2
|
||||
re2char(int c0, int c1)
|
||||
{
|
||||
Re2 c;
|
||||
|
||||
c.beg = ral(Tclass);
|
||||
c.beg->lo = c0 & 0xff;
|
||||
c.beg->hi = c1 & 0xff;
|
||||
c.end = c.beg;
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
reprint1(Re *a)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
loop:
|
||||
if(a == 0)
|
||||
return;
|
||||
if(a->gen == gen)
|
||||
return;
|
||||
a->gen = gen;
|
||||
print("%p: ", a);
|
||||
switch(a->type) {
|
||||
default:
|
||||
print("type %d\n", a->type);
|
||||
error("print1 type");
|
||||
|
||||
case Tcase:
|
||||
print("case ->%p\n", a->next);
|
||||
for(i=0; i<256; i++)
|
||||
if(a->cases[i]) {
|
||||
for(j=i+1; j<256; j++)
|
||||
if(a->cases[i] != a->cases[j])
|
||||
break;
|
||||
print(" [%.2x-%.2x] ->%p\n", i, j-1, a->cases[i]);
|
||||
i = j-1;
|
||||
}
|
||||
for(i=0; i<256; i++)
|
||||
reprint1(a->cases[i]);
|
||||
break;
|
||||
|
||||
case Tbegin:
|
||||
print("^ ->%p\n", a->next);
|
||||
break;
|
||||
|
||||
case Tend:
|
||||
print("$ ->%p\n", a->next);
|
||||
break;
|
||||
|
||||
case Tclass:
|
||||
print("[%.2x-%.2x] ->%p\n", a->lo, a->hi, a->next);
|
||||
break;
|
||||
|
||||
case Tor:
|
||||
case Talt:
|
||||
print("| %p ->%p\n", a->alt, a->next);
|
||||
reprint1(a->alt);
|
||||
break;
|
||||
}
|
||||
a = a->next;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void
|
||||
reprint(char *s, Re *r)
|
||||
{
|
||||
print("%s:\n", s);
|
||||
gen++;
|
||||
reprint1(r);
|
||||
print("\n\n");
|
||||
}
|
|
@ -3,11 +3,11 @@ PLAN9=../..
|
|||
|
||||
TARG=`ls *.c | sed 's/\.c//'`
|
||||
LDFLAGS=$LDFLAGS
|
||||
SHORTLIB=sec fs mux regexp9 thread bio 9
|
||||
SHORTLIB=mach sec fs mux regexp9 thread bio 9
|
||||
|
||||
<$PLAN9/src/mkmany
|
||||
|
||||
BUGGERED='CVS|9term|faces|factotum|htmlfmt|mk|rio|upas|vac|venti'
|
||||
BUGGERED='CVS|faces|factotum|htmlfmt|mk|upas|vac|venti'
|
||||
DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"`
|
||||
|
||||
<$PLAN9/src/mkdirs
|
||||
|
|
|
@ -97,6 +97,7 @@ static Dirtab dir[NDIR] =
|
|||
static int ndir = NQID;
|
||||
|
||||
static int srvfd;
|
||||
#define clock plumbclock /* SunOS name clash */
|
||||
static int clock;
|
||||
static Fid *fids[Nhash];
|
||||
static QLock readlock;
|
||||
|
|
|
@ -54,9 +54,10 @@ threadmain(int argc, char *argv[])
|
|||
error("can't initialize $user or $home: %r");
|
||||
if(plumbfile == nil){
|
||||
sprint(buf, "%s/lib/plumbing", home);
|
||||
if(access(buf, 0) < 0)
|
||||
sprint(buf, "#9/plumb/initial.plumbing");
|
||||
if(access(buf, 0) >= 0)
|
||||
plumbfile = estrdup(buf);
|
||||
else
|
||||
plumbfile = unsharp("#9/plumb/initial.plumbing");
|
||||
}
|
||||
|
||||
fd = open(plumbfile, OREAD);
|
||||
|
|
|
@ -415,7 +415,7 @@ include(char *s)
|
|||
fd = open(t, OREAD);
|
||||
if(fd<0 && t[0]!='/' && strncmp(t, "./", 2)!=0 && strncmp(t, "../", 3)!=0){
|
||||
snprint(buf, sizeof buf, "#9/plumb/%s", t);
|
||||
t = buf;
|
||||
t = unsharp(buf);
|
||||
fd = open(t, OREAD);
|
||||
}
|
||||
if(fd < 0)
|
||||
|
|
|
@ -27,20 +27,10 @@ char *syssigname[]={
|
|||
char*
|
||||
Rcmain(void)
|
||||
{
|
||||
return "#9/rcmain";
|
||||
/*
|
||||
static char buf[256];
|
||||
char *root;
|
||||
|
||||
root = getenv("PLAN9");
|
||||
if(root == nil)
|
||||
root = "/usr/local/plan9";
|
||||
snprint(buf, sizeof buf, "%s/rcmain", root);
|
||||
return buf;
|
||||
*/
|
||||
return unsharp("#9/rcmain");
|
||||
}
|
||||
|
||||
char Fdprefix[]="#d/";
|
||||
char Fdprefix[]="/dev/fd/";
|
||||
void execfinit(void);
|
||||
void execbind(void);
|
||||
void execmount(void);
|
||||
|
|
27
src/cmd/rio/Imakefile
Normal file
27
src/cmd/rio/Imakefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
INCLUDES = -I$(TOP)
|
||||
DEPLIBS = $(DEPXLIB)
|
||||
LOCAL_LIBRARIES = $(XLIB)
|
||||
DEFINES = -DSHAPE # -g3 -DDEBUG -DDEBUG_EV
|
||||
SRCS = main.c event.c manage.c menu.c client.c grab.c cursor.c error.c color.c
|
||||
OBJS = main.o event.o manage.o menu.o client.o grab.o cursor.o error.o color.o
|
||||
HFILES = dat.h fns.h patchlevel.h
|
||||
MFILES = README 9wm.man Imakefile Makefile.no-imake
|
||||
|
||||
ComplexProgramTarget(rio)
|
||||
|
||||
bun:
|
||||
bundle $(MFILES) $(SRCS) $(HFILES) >bun
|
||||
|
||||
dist:
|
||||
bundle $(MFILES) main.c event.c manage.c >bun1
|
||||
bundle menu.c client.c grab.c cursor.c error.c $(HFILES) >bun2
|
||||
|
||||
trout: 9wm.man
|
||||
troff -man 9wm.man >trout
|
||||
|
||||
vu: trout
|
||||
xditview trout
|
||||
|
||||
clean::
|
||||
$(RM) bun bun[12] trout core
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
#include "fns.h"
|
||||
|
||||
unsigned long
|
||||
colorpixel(Display *dpy, int depth, ulong rgb)
|
||||
colorpixel(Display *dpy, int depth, unsigned long rgb)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#ifdef SHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#endif
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "patchlevel.h"
|
||||
|
@ -70,12 +73,15 @@ main(int argc, char *argv[])
|
|||
int i, background, do_exit, do_restart;
|
||||
char *fname;
|
||||
int shape_event;
|
||||
#ifdef SHAPE
|
||||
int dummy;
|
||||
#endif
|
||||
|
||||
shape_event = 0;
|
||||
myargv = argv; /* for restart */
|
||||
|
||||
do_exit = do_restart = 0;
|
||||
background = 1;
|
||||
background = 0;
|
||||
font = 0;
|
||||
fname = 0;
|
||||
for (i = 1; i < argc; i++)
|
||||
|
@ -289,12 +295,11 @@ initscreen(ScreenInfo *s, int i, int background)
|
|||
XSync(dpy, False);
|
||||
|
||||
if (background) {
|
||||
/*
|
||||
XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap);
|
||||
XClearWindow(dpy, s->root);
|
||||
*/
|
||||
} else
|
||||
system("xsetroot -solid grey30");
|
||||
}
|
||||
|
||||
s->menuwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 2, colorpixel(dpy, s->depth, 0x88CC88), colorpixel(dpy, s->depth, 0xE9FFE9));
|
||||
s->sweepwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 4, s->red, colorpixel(dpy, s->depth, 0xEEEEEE));
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
PLAN9=../../..
|
||||
<$PLAN9/src/mkhdr
|
||||
|
||||
OFILES=\
|
||||
|
@ -18,3 +19,7 @@ TARG=rio
|
|||
LDFLAGS=-L$X11/lib -lXext -lX11
|
||||
|
||||
<$PLAN9/src/mkone
|
||||
|
||||
CFLAGS=$CFLAGS -DSHAPE -I$X11/include
|
||||
|
||||
|
||||
|
|
|
@ -460,6 +460,9 @@ main(int argc, char *argv[])
|
|||
int low;
|
||||
Bits h;
|
||||
|
||||
codefile = unsharp(codefile);
|
||||
brfile = unsharp(brfile);
|
||||
|
||||
Binit(&bin, 0, OREAD);
|
||||
Binit(&bout, 1, OWRITE);
|
||||
for(i=0; c = "aeiouyAEIOUY"[i]; i++)
|
||||
|
|
|
@ -399,7 +399,7 @@ others(void)
|
|||
{
|
||||
int c, i, j;
|
||||
|
||||
finput = Bopen(parser, OREAD);
|
||||
finput = Bopen(unsharp(parser), OREAD);
|
||||
if(finput == 0)
|
||||
error("cannot open parser %s: %r", parser);
|
||||
warray("yyr1", levprd, nprod);
|
||||
|
|
|
@ -14,7 +14,7 @@ static struct {
|
|||
};
|
||||
|
||||
char*
|
||||
_p9translate(char *old)
|
||||
plan9translate(char *old)
|
||||
{
|
||||
char *new;
|
||||
int i, olen, nlen, len;
|
||||
|
@ -36,7 +36,7 @@ _p9translate(char *old)
|
|||
len = strlen(old)+nlen-olen;
|
||||
new = malloc(len+1);
|
||||
if(new == nil)
|
||||
return nil;
|
||||
return "<out of memory>";
|
||||
strcpy(new, replace[i].new);
|
||||
strcpy(new+nlen, old+olen);
|
||||
assert(strlen(new) == len);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#include <u.h>
|
||||
#define NOPLAN9DEFINES
|
||||
#include <libc.h>
|
||||
|
||||
char *_p9translate(char*);
|
||||
|
||||
int
|
||||
p9access(char *xname, int what)
|
||||
{
|
||||
int ret;
|
||||
char *name;
|
||||
|
||||
if((name = _p9translate(xname)) == nil)
|
||||
return -1;
|
||||
ret = access(name, what);
|
||||
if(name != xname)
|
||||
free(name);
|
||||
return ret;
|
||||
}
|
|
@ -40,7 +40,8 @@ p9announce(char *addr, char *dir)
|
|||
char *net;
|
||||
u32int host;
|
||||
int port, s;
|
||||
int n, sn;
|
||||
int n;
|
||||
socklen_t sn;
|
||||
struct sockaddr_in sa;
|
||||
struct sockaddr_un sun;
|
||||
|
||||
|
@ -72,7 +73,7 @@ p9announce(char *addr, char *dir)
|
|||
if((s = socket(AF_INET, proto, 0)) < 0)
|
||||
return -1;
|
||||
sn = sizeof n;
|
||||
if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&n, &sn) >= 0
|
||||
if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0
|
||||
&& n == SOCK_STREAM){
|
||||
n = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
|
||||
|
|
|
@ -3,16 +3,10 @@
|
|||
#include <libc.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
extern char *_p9translate(char*);
|
||||
|
||||
int
|
||||
p9create(char *xpath, int mode, ulong perm)
|
||||
p9create(char *path, int mode, ulong perm)
|
||||
{
|
||||
int fd, cexec, umode, rclose;
|
||||
char *path;
|
||||
|
||||
if((path = _p9translate(xpath)) == nil)
|
||||
return -1;
|
||||
|
||||
cexec = mode&OCEXEC;
|
||||
rclose = mode&ORCLOSE;
|
||||
|
@ -48,7 +42,5 @@ out:
|
|||
if(rclose)
|
||||
remove(path);
|
||||
}
|
||||
if(path != xpath)
|
||||
free(path);
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ ct_numb(char *cp, int n)
|
|||
char*
|
||||
asctime(Tm *t)
|
||||
{
|
||||
int i;
|
||||
char *ncp;
|
||||
static char cbuf[30];
|
||||
|
||||
|
@ -32,6 +33,12 @@ asctime(Tm *t)
|
|||
ct_numb(cbuf+14, t->min+100);
|
||||
ct_numb(cbuf+17, t->sec+100);
|
||||
ncp = t->zone;
|
||||
for(i=0; i<3; i++)
|
||||
if(ncp[i] == 0)
|
||||
break;
|
||||
for(; i<3; i++)
|
||||
ncp[i] = '?';
|
||||
ncp = t->zone;
|
||||
cbuf[20] = *ncp++;
|
||||
cbuf[21] = *ncp++;
|
||||
cbuf[22] = *ncp;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <stdlib.h> /* setenv etc. */
|
||||
|
||||
#include <u.h>
|
||||
#include <stdlib.h> /* setenv etc. */
|
||||
#define NOPLAN9DEFINES
|
||||
#include <libc.h>
|
||||
#include <time.h>
|
||||
|
@ -25,6 +24,8 @@ static Tm bigtm;
|
|||
static void
|
||||
tm2Tm(struct tm *tm, Tm *bigtm)
|
||||
{
|
||||
char *s;
|
||||
|
||||
memset(bigtm, 0, sizeof *bigtm);
|
||||
bigtm->sec = tm->tm_sec;
|
||||
bigtm->min = tm->tm_min;
|
||||
|
@ -39,6 +40,13 @@ tm2Tm(struct tm *tm, Tm *bigtm)
|
|||
#ifdef _HAVETZOFF
|
||||
bigtm->tzoff = tm->tm_gmtoff;
|
||||
#endif
|
||||
if(bigtm->zone[0] == 0){
|
||||
s = getenv("TIMEZONE");
|
||||
if(s){
|
||||
strecpy(bigtm->zone, bigtm->zone+4, tm->tm_zone);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -18,7 +18,7 @@ mygetdents(int fd, struct dirent *buf, int n)
|
|||
nn = getdirentries(fd, (void*)buf, n, &off);
|
||||
return nn;
|
||||
}
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
static int
|
||||
mygetdents(int fd, struct dirent *buf, int n)
|
||||
{
|
||||
|
@ -171,7 +171,7 @@ dirreadall(int fd, Dir **d)
|
|||
ts += n;
|
||||
}
|
||||
if(ts >= 0)
|
||||
ts = dirpackage(fd, buf, ts, d);
|
||||
ts = dirpackage(fd, (char*)buf, ts, d);
|
||||
free(buf);
|
||||
if(ts == 0 && n < 0)
|
||||
return -1;
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
* okay.
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <lib9.h>
|
||||
#include <libc.h>
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
1
src/lib9/ffork-OpenBSD.c
Normal file
1
src/lib9/ffork-OpenBSD.c
Normal file
|
@ -0,0 +1 @@
|
|||
#include "ffork-pthread.c"
|
|
@ -1,6 +1,5 @@
|
|||
#include <pwd.h>
|
||||
|
||||
#include <u.h>
|
||||
#include <pwd.h>
|
||||
#include <libc.h>
|
||||
|
||||
char*
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <u.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <lib9.h>
|
||||
#include <libc.h>
|
||||
|
||||
int _ntas;
|
||||
static int
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <u.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <lib9.h>
|
||||
#include <libc.h>
|
||||
|
||||
void*
|
||||
mallocz(unsigned long n, int clr)
|
||||
|
|
|
@ -69,8 +69,6 @@ LIB9OFILES=\
|
|||
_p9dialparse.$O\
|
||||
_p9dir.$O\
|
||||
_p9proc.$O\
|
||||
_p9translate.$O\
|
||||
access.$O\
|
||||
announce.$O\
|
||||
argv0.$O\
|
||||
atexit.$O\
|
||||
|
@ -100,6 +98,7 @@ LIB9OFILES=\
|
|||
exec.$O\
|
||||
fcallfmt.$O\
|
||||
ffork-$SYSNAME.$O\
|
||||
get9root.$O\
|
||||
getcallerpc-$OBJTYPE.$O\
|
||||
getenv.$O\
|
||||
getfields.$O\
|
||||
|
@ -142,6 +141,7 @@ LIB9OFILES=\
|
|||
u16.$O\
|
||||
u32.$O\
|
||||
u64.$O\
|
||||
unsharp.$O\
|
||||
wait.$O\
|
||||
waitpid.$O\
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <signal.h>
|
||||
|
||||
#include <u.h>
|
||||
#include <signal.h>
|
||||
#define NOPLAN9DEFINES
|
||||
#include <libc.h>
|
||||
#include "9proc.h"
|
||||
|
|
|
@ -2,12 +2,9 @@
|
|||
#define NOPLAN9DEFINES
|
||||
#include <libc.h>
|
||||
|
||||
extern char* _p9translate(char*);
|
||||
|
||||
int
|
||||
p9open(char *xname, int mode)
|
||||
p9open(char *name, int mode)
|
||||
{
|
||||
char *name;
|
||||
int cexec, rclose;
|
||||
int fd, umode;
|
||||
|
||||
|
@ -23,8 +20,6 @@ p9open(char *xname, int mode)
|
|||
werrstr("mode not supported");
|
||||
return -1;
|
||||
}
|
||||
if((name = _p9translate(xname)) == nil)
|
||||
return -1;
|
||||
fd = open(name, umode);
|
||||
if(fd >= 0){
|
||||
if(cexec)
|
||||
|
@ -32,7 +27,5 @@ p9open(char *xname, int mode)
|
|||
if(rclose)
|
||||
remove(name);
|
||||
}
|
||||
if(name != xname)
|
||||
free(name);
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
/* Could use futex(2) here instead of signals? */
|
||||
|
||||
#include "rendez-signal.c"
|
||||
|
|
1
src/lib9/rendez-OpenBSD.c
Normal file
1
src/lib9/rendez-OpenBSD.c
Normal file
|
@ -0,0 +1 @@
|
|||
#include "rendez-signal.c"
|
|
@ -32,9 +32,10 @@
|
|||
* shared memory and mutexes.
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <lib9.h>
|
||||
#include <libc.h>
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <u.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/resource.h>
|
||||
#define NOPLAN9DEFINES
|
||||
#include <libc.h>
|
||||
|
||||
|
|
|
@ -16,10 +16,12 @@ openfont(Display *d, char *name)
|
|||
|
||||
if(fd < 0 && strncmp(name, "/lib/font/bit/", 14) == 0){
|
||||
nambuf = smprint("#9/font/%s", name+14);
|
||||
if(nambuf == nil)
|
||||
return 0;
|
||||
nambuf = unsharp(nambuf);
|
||||
if(nambuf == nil)
|
||||
return 0;
|
||||
if((fd = open(nambuf, OREAD)) < 0){
|
||||
fprint(2, "failed at %s\n", nambuf);
|
||||
free(nambuf);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -185,26 +185,22 @@ xattach(char *label)
|
|||
/*
|
||||
* Figure out underlying screen format.
|
||||
*/
|
||||
_x.depth = DefaultDepth(_x.display, xrootid);
|
||||
if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi)
|
||||
|| XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){
|
||||
_x.vis = xvi.visual;
|
||||
_x.depth = 16;
|
||||
_x.usetable = 1;
|
||||
}
|
||||
else
|
||||
if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi)
|
||||
|| XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){
|
||||
_x.vis = xvi.visual;
|
||||
_x.depth = 15;
|
||||
_x.usetable = 1;
|
||||
}
|
||||
else
|
||||
if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi)
|
||||
|| XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){
|
||||
_x.vis = xvi.visual;
|
||||
_x.depth = 24;
|
||||
_x.usetable = 1;
|
||||
}
|
||||
else
|
||||
if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi)
|
||||
|
@ -218,6 +214,7 @@ xattach(char *label)
|
|||
_x.depth = 8;
|
||||
}
|
||||
else{
|
||||
_x.depth = DefaultDepth(_x.display, xrootid);
|
||||
if(_x.depth != 8){
|
||||
werrstr("can't understand depth %d screen", _x.depth);
|
||||
goto err0;
|
||||
|
@ -225,6 +222,9 @@ xattach(char *label)
|
|||
_x.vis = DefaultVisual(_x.display, xrootid);
|
||||
}
|
||||
|
||||
if(DefaultDepth(_x.display, xrootid) == _x.depth)
|
||||
_x.usetable = 1;
|
||||
|
||||
/*
|
||||
* _x.depth is only the number of significant pixel bits,
|
||||
* not the total number of pixel bits. We need to walk the
|
||||
|
@ -298,7 +298,7 @@ xattach(char *label)
|
|||
Dx(r), /* width */
|
||||
Dy(r), /* height */
|
||||
0, /* border width */
|
||||
DefaultDepthOfScreen(xscreen), /* depth */
|
||||
_x.depth, /* depth */
|
||||
InputOutput, /* class */
|
||||
_x.vis, /* visual */
|
||||
/* valuemask */
|
||||
|
@ -562,6 +562,18 @@ setupcmap(XWindow w)
|
|||
return 0;
|
||||
|
||||
if(_x.depth >= 24) {
|
||||
/*
|
||||
* This is needed for SunOS. Ask Axel Belinfante.
|
||||
*/
|
||||
if(_x.usetable == 0){
|
||||
_x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocAll);
|
||||
XStoreColors(_x.display, _x.cmap, _x.map, 256);
|
||||
for(i = 0; i < 256; i++){
|
||||
_x.tox11[i] = i;
|
||||
_x.toplan9[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The pixel value returned from XGetPixel needs to
|
||||
* be converted to RGB so we can call rgb2cmap()
|
||||
|
@ -573,7 +585,6 @@ setupcmap(XWindow w)
|
|||
* some displays say MSB even though they run on LSB.
|
||||
* Besides, this is more anal.
|
||||
*/
|
||||
|
||||
c = _x.map[19]; /* known to have different R, G, B values */
|
||||
if(!XAllocColor(_x.display, _x.cmap, &c)){
|
||||
werrstr("XAllocColor: %r");
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include <keyboard.h>
|
||||
#include "x11-memdraw.h"
|
||||
|
||||
#undef time
|
||||
|
||||
|
||||
static int
|
||||
__xtoplan9kbd(XEvent *e)
|
||||
{
|
||||
|
|
|
@ -68,7 +68,6 @@ plumbsendtofid(Fid *fid, Plumbmsg *m)
|
|||
if(buf == nil)
|
||||
return -1;
|
||||
n = fswrite(fid, buf, n);
|
||||
fprint(2, "fswrite %d\n", n);
|
||||
free(buf);
|
||||
return n;
|
||||
}
|
||||
|
|
49
src/libthread/asm-OpenBSD-386.s
Normal file
49
src/libthread/asm-OpenBSD-386.s
Normal file
|
@ -0,0 +1,49 @@
|
|||
.globl _setlabel
|
||||
.type _setlabel,@function
|
||||
|
||||
_setlabel:
|
||||
movl 4(%esp), %eax
|
||||
movl 0(%esp), %edx
|
||||
movl %edx, 0(%eax)
|
||||
movl %ebx, 4(%eax)
|
||||
movl %esp, 8(%eax)
|
||||
movl %ebp, 12(%eax)
|
||||
movl %esi, 16(%eax)
|
||||
movl %edi, 20(%eax)
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
|
||||
.globl _gotolabel
|
||||
.type _gotolabel,@function
|
||||
|
||||
_gotolabel:
|
||||
movl 4(%esp), %edx
|
||||
movl 0(%edx), %ecx
|
||||
movl 4(%edx), %ebx
|
||||
movl 8(%edx), %esp
|
||||
movl 12(%edx), %ebp
|
||||
movl 16(%edx), %esi
|
||||
movl 20(%edx), %edi
|
||||
xorl %eax, %eax
|
||||
incl %eax
|
||||
movl %ecx, 0(%esp)
|
||||
ret
|
||||
|
||||
|
||||
# .globl _xinc
|
||||
# _xinc:
|
||||
# movl 4(%esp), %eax
|
||||
# lock incl 0(%eax)
|
||||
# ret
|
||||
#
|
||||
# .globl _xdec
|
||||
# _xdec:
|
||||
# movl 4(%esp), %eax
|
||||
# lock decl 0(%eax)
|
||||
# jz iszero
|
||||
# movl $1, %eax
|
||||
# ret
|
||||
# iszero:
|
||||
# movl $0, %eax
|
||||
# ret
|
||||
#
|
|
@ -3,8 +3,8 @@
|
|||
#include "threadimpl.h"
|
||||
|
||||
static void efork(int[3], int[2], char*, char**);
|
||||
void
|
||||
threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
|
||||
static void
|
||||
_threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs)
|
||||
{
|
||||
int pfd[2];
|
||||
int n, pid;
|
||||
|
@ -40,6 +40,8 @@ threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
|
|||
efork(fd, pfd, prog, args);
|
||||
_exit(0);
|
||||
default:
|
||||
if(freeargs)
|
||||
free(args);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -68,10 +70,43 @@ Bad:
|
|||
sendul(pidc, ~0);
|
||||
}
|
||||
|
||||
void
|
||||
threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
|
||||
{
|
||||
_threadexec(pidc, fd, prog, args, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The &f+1 trick doesn't work on SunOS, so we might
|
||||
* as well bite the bullet and do this correctly.
|
||||
*/
|
||||
void
|
||||
threadexecl(Channel *pidc, int fd[3], char *f, ...)
|
||||
{
|
||||
threadexec(pidc, fd, f, &f+1);
|
||||
char **args, *s;
|
||||
int n;
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, f);
|
||||
for(n=0; va_arg(arg, char*) != 0; n++)
|
||||
;
|
||||
n++;
|
||||
va_end(arg);
|
||||
|
||||
args = malloc(n*sizeof(args[0]));
|
||||
if(args == nil){
|
||||
if(pidc)
|
||||
sendul(pidc, ~0);
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(arg, f);
|
||||
for(n=0; (s=va_arg(arg, char*)) != 0; n++)
|
||||
args[n] = s;
|
||||
args[n] = 0;
|
||||
va_end(arg);
|
||||
|
||||
_threadexec(pidc, fd, f, args, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
typedef struct Label Label;
|
||||
#define LABELDPC 0
|
||||
|
||||
#if defined (__i386__) && (defined(__FreeBSD__) || defined(__linux__))
|
||||
#if defined (__i386__) && (defined(__FreeBSD__) || defined(__linux__) || defined(__OpenBSD__))
|
||||
struct Label
|
||||
{
|
||||
ulong pc;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<mkhdr
|
||||
|
||||
BUGGERED='9p|html|httpd|ip|venti'
|
||||
BUGGERED='9p|fmt|html|httpd|ip|utf|venti'
|
||||
LIBDIRS=`ls -ld lib* | sed -n 's/^d.* //p' |egrep -v "^lib($BUGGERED)$"`
|
||||
|
||||
DIRS=\
|
||||
|
|
Loading…
Reference in a new issue