aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-03-25 23:03:57 +0000
committerrsc <devnull@localhost>2004-03-25 23:03:57 +0000
commit8ad517944e46710ab832350c0dc3fc4e9239f7e2 (patch)
tree7b99a1833e1b303719c2aac75e3f7e82482b42ab
parentcb27443abf3d6af6ab52377c71c843e619928433 (diff)
downloadplan9port-8ad517944e46710ab832350c0dc3fc4e9239f7e2.tar.gz
plan9port-8ad517944e46710ab832350c0dc3fc4e9239f7e2.tar.bz2
plan9port-8ad517944e46710ab832350c0dc3fc4e9239f7e2.zip
Today's changes.
More changes.
-rw-r--r--include/fmt.h1
-rw-r--r--include/lib9.h876
-rw-r--r--include/libString.h2
-rw-r--r--include/libc.h794
-rw-r--r--include/u.h93
-rw-r--r--src/cmd/9pserve.c2
-rw-r--r--src/cmd/9term/9term.c456
-rw-r--r--src/cmd/9term/9term.h21
-rw-r--r--src/cmd/9term/FreeBSD.c40
-rw-r--r--src/cmd/9term/Linux.c48
-rw-r--r--src/cmd/9term/SunOS.c37
-rw-r--r--src/cmd/9term/mkfile8
-rw-r--r--src/cmd/9term/rcstart.c51
-rw-r--r--src/cmd/9term/term.h5
-rw-r--r--src/cmd/9term/win.c (renamed from src/cmd/win.c)50
-rw-r--r--src/cmd/acme/acme.c24
-rw-r--r--src/cmd/acme/dat.h1
-rw-r--r--src/cmd/acme/ecmd.c2
-rw-r--r--src/cmd/acme/exec.c4
-rw-r--r--src/cmd/acme/fns.h5
-rw-r--r--src/cmd/acme/fsys.c44
-rw-r--r--src/cmd/acme/look.c12
-rw-r--r--src/cmd/acme/text.c2
-rw-r--r--src/cmd/acme/util.c23
-rw-r--r--src/cmd/acme/xfid.c3
-rw-r--r--src/cmd/dict/dict.c2
-rw-r--r--src/cmd/diff/diff.h2
-rw-r--r--src/cmd/diff/main.c2
-rw-r--r--src/cmd/fortune.c8
-rw-r--r--src/cmd/grep/comp.c277
-rw-r--r--src/cmd/grep/grep.h125
-rw-r--r--src/cmd/grep/grep.y226
-rw-r--r--src/cmd/grep/main.c260
-rw-r--r--src/cmd/grep/mkfile20
-rw-r--r--src/cmd/grep/sub.c317
-rw-r--r--src/cmd/mkfile4
-rw-r--r--src/cmd/plumb/fsys.c1
-rw-r--r--src/cmd/plumb/plumber.c7
-rw-r--r--src/cmd/plumb/rules.c2
-rw-r--r--src/cmd/rc/plan9ish.c14
-rw-r--r--src/cmd/rio/Imakefile27
-rw-r--r--src/cmd/rio/color.c2
-rw-r--r--src/cmd/rio/main.c13
-rw-r--r--src/cmd/rio/mkfile5
-rw-r--r--src/cmd/spell/sprog.c3
-rw-r--r--src/cmd/yacc.c2
-rw-r--r--src/lib9/_p9translate.c4
-rw-r--r--src/lib9/access.c19
-rw-r--r--src/lib9/announce.c5
-rw-r--r--src/lib9/create.c10
-rw-r--r--src/lib9/ctime.c7
-rw-r--r--src/lib9/date.c12
-rw-r--r--src/lib9/dirread.c4
-rw-r--r--src/lib9/errstr.c3
-rw-r--r--src/lib9/ffork-OpenBSD.c1
-rw-r--r--src/lib9/getuser.c3
-rw-r--r--src/lib9/lock.c3
-rw-r--r--src/lib9/mallocz.c3
-rw-r--r--src/lib9/mkfile4
-rw-r--r--src/lib9/notify.c3
-rw-r--r--src/lib9/open.c9
-rw-r--r--src/lib9/rendez-Linux.c2
-rw-r--r--src/lib9/rendez-OpenBSD.c1
-rw-r--r--src/lib9/rendez-pthread.c3
-rw-r--r--src/lib9/time.c4
-rw-r--r--src/libdraw/openfont.c4
-rw-r--r--src/libdraw/x11-init.c23
-rw-r--r--src/libdraw/x11-itrans.c3
-rwxr-xr-xsrc/libplumb/mesg.c1
-rw-r--r--src/libthread/asm-OpenBSD-386.s49
-rw-r--r--src/libthread/exec-unix.c41
-rw-r--r--src/libthread/label.h2
-rw-r--r--src/mkfile2
73 files changed, 2860 insertions, 1288 deletions
diff --git a/include/fmt.h b/include/fmt.h
index befea2e3..4cee8fb5 100644
--- a/include/fmt.h
+++ b/include/fmt.h
@@ -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);
diff --git a/include/lib9.h b/include/lib9.h
index 1373ce15..07a1f976 100644
--- a/include/lib9.h
+++ b/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>
diff --git a/include/libString.h b/include/libString.h
index d8487066..1a560b6f 100644
--- a/include/libString.h
+++ b/include/libString.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 */
diff --git a/include/libc.h b/include/libc.h
index 25b042c1..64bb0867 100644
--- a/include/libc.h
+++ b/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_ */
diff --git a/include/u.h b/include/u.h
index e69de29b..4716ce4f 100644
--- a/include/u.h
+++ b/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
diff --git a/src/cmd/9pserve.c b/src/cmd/9pserve.c
index 8acd5524..644385c1 100644
--- a/src/cmd/9pserve.c
+++ b/src/cmd/9pserve.c
@@ -1150,7 +1150,7 @@ rewritehdr(Fcall *f, uchar *pkt)
}
}
-#ifdef _LIB9_H_
+#ifdef _LIBC_H_
/* unix select-based polling */
struct Ioproc
{
diff --git a/src/cmd/9term/9term.c b/src/cmd/9term/9term.c
index c5a2c424..50c0cfc9 100644
--- a/src/cmd/9term/9term.c
+++ b/src/cmd/9term/9term.c
@@ -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 CUT 0x18 /* ctrl-x */
+#define COPY 0x03 /* crtl-c */
+#define PASTE 0x16 /* crtl-v */
#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:
- snarf();
+ 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;
+ case Kdown:
+ setorigin(line2q(t.f->maxlines/3), 1);
+ if(t.qh<=t.org+t.f->nchars)
+ consread();
return;
- }else if(r == CUT){
+ 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);
}
@@ -1322,61 +1486,6 @@ clickmatch(int cl, int cr, int dir, uint *q)
}
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)
{
Frame *f;
@@ -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)
diff --git a/src/cmd/9term/9term.h b/src/cmd/9term/9term.h
index 4e8d61f3..57a8359e 100644
--- a/src/cmd/9term/9term.h
+++ b/src/cmd/9term/9term.h
@@ -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[];
diff --git a/src/cmd/9term/FreeBSD.c b/src/cmd/9term/FreeBSD.c
index e8b894dc..7022d4d9 100644
--- a/src/cmd/9term/FreeBSD.c
+++ b/src/cmd/9term/FreeBSD.c
@@ -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)
+getpts(int fd[], char *slave)
{
- USED(pid);
- USED(wdir);
- USED(bufn);
- return -1;
+ return openpty(&fd[1], &fd[0], slave, 0, 0);
}
int
-getpts(int fd[], char *slave)
+childpty(int fd[], char *slave)
{
- return openpty(&fd[1], &fd[0], slave, 0, 0);
+ 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;
+}
+
diff --git a/src/cmd/9term/Linux.c b/src/cmd/9term/Linux.c
index 7dd22371..872417e6 100644
--- a/src/cmd/9term/Linux.c
+++ b/src/cmd/9term/Linux.c
@@ -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)
+getpts(int fd[], char *slave)
{
- 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';
+ openpty(&fd[1], &fd[0], slave, 0, 0);
return 0;
}
int
-getpts(int fd[], char *slave)
+childpty(int fd[], char *slave)
{
- openpty(&fd[1], &fd[0], slave, 0, 0);
- return 0;
+ 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;
+}
+
diff --git a/src/cmd/9term/SunOS.c b/src/cmd/9term/SunOS.c
index 6a37ab33..d7db9fc5 100644
--- a/src/cmd/9term/SunOS.c
+++ b/src/cmd/9term/SunOS.c
@@ -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;
+}
+
diff --git a/src/cmd/9term/mkfile b/src/cmd/9term/mkfile
index d0d5ca72..8701ad9c 100644
--- a/src/cmd/9term/mkfile
+++ b/src/cmd/9term/mkfile
@@ -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
diff --git a/src/cmd/9term/rcstart.c b/src/cmd/9term/rcstart.c
new file mode 100644
index 00000000..7596bc41
--- /dev/null
+++ b/src/cmd/9term/rcstart.c
@@ -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;
+}
+
diff --git a/src/cmd/9term/term.h b/src/cmd/9term/term.h
new file mode 100644
index 00000000..a608b7ed
--- /dev/null
+++ b/src/cmd/9term/term.h
@@ -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*);
diff --git a/src/cmd/win.c b/src/cmd/9term/win.c
index 7f15f057..95d84a32 100644
--- a/src/cmd/win.c
+++ b/src/cmd/9term/win.c
@@ -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;
diff --git a/src/cmd/acme/acme.c b/src/cmd/acme/acme.c
index d4b4cad8..9636beab 100644
--- a/src/cmd/acme/acme.c
+++ b/src/cmd/acme/acme.c
@@ -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 = &pm;
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;
}
diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h
index 94cfa383..338a1ff8 100644
--- a/src/cmd/acme/dat.h
+++ b/src/cmd/acme/dat.h
@@ -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
diff --git a/src/cmd/acme/ecmd.c b/src/cmd/acme/ecmd.c
index 0dfae90a..7ccb9427 100644
--- a/src/cmd/acme/ecmd.c
+++ b/src/cmd/acme/ecmd.c
@@ -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){
diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c
index 74f9f47c..0e3389d6 100644
--- a/src/cmd/acme/exec.c
+++ b/src/cmd/acme/exec.c
@@ -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.
diff --git a/src/cmd/acme/fns.h b/src/cmd/acme/fns.h
index 9fba7d7a..c164bb3b 100644
--- a/src/cmd/acme/fns.h
+++ b/src/cmd/acme/fns.h
@@ -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))
diff --git a/src/cmd/acme/fsys.c b/src/cmd/acme/fsys.c
index f178f864..af4255c8 100644
--- a/src/cmd/acme/fsys.c
+++ b/src/cmd/acme/fsys.c
@@ -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)
@@ -187,6 +191,14 @@ fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl)
}
void
+fsysincid(Mntdir *m)
+{
+ qlock(&mnt.lk);
+ m->ref++;
+ qunlock(&mnt.lk);
+}
+
+void
fsysdelid(Mntdir *idm)
{
Mntdir *m, *prev;
@@ -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));
}
diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c
index f6c4d4ee..70233826 100644
--- a/src/cmd/acme/look.c
+++ b/src/cmd/acme/look.c
@@ -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;
diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c
index 8bdf0b78..c0cd7ec1 100644
--- a/src/cmd/acme/text.c
+++ b/src/cmd/acme/text.c
@@ -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)){
diff --git a/src/cmd/acme/util.c b/src/cmd/acme/util.c
index de71107a..a7307e06 100644
--- a/src/cmd/acme/util.c
+++ b/src/cmd/acme/util.c
@@ -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
diff --git a/src/cmd/acme/xfid.c b/src/cmd/acme/xfid.c
index b3bef2cd..839308ee 100644
--- a/src/cmd/acme/xfid.c
+++ b/src/cmd/acme/xfid.c
@@ -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;
diff --git a/src/cmd/dict/dict.c b/src/cmd/dict/dict.c
index 8cbf6aac..a3ddd890 100644
--- a/src/cmd/dict/dict.c
+++ b/src/cmd/dict/dict.c
@@ -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);
diff --git a/src/cmd/diff/diff.h b/src/cmd/diff/diff.h
index 8e56765f..c809ae81 100644
--- a/src/cmd/diff/diff.h
+++ b/src/cmd/diff/diff.h
@@ -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 */
diff --git a/src/cmd/diff/main.c b/src/cmd/diff/main.c
index 43eb6dd1..00f69a3e 100644
--- a/src/cmd/diff/main.c
+++ b/src/cmd/diff/main.c
@@ -26,6 +26,8 @@ void
done(int status)
{
rmtmpfiles();
+Bflush(&stdout);
+Bterm(&stdout);
switch(status)
{
case 0:
diff --git a/src/cmd/fortune.c b/src/cmd/fortune.c
index f3acfca2..4aa895fe 100644
--- a/src/cmd/fortune.c
+++ b/src/cmd/fortune.c
@@ -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);
diff --git a/src/cmd/grep/comp.c b/src/cmd/grep/comp.c
new file mode 100644
index 00000000..4a3f3e8f
--- /dev/null
+++ b/src/cmd/grep/comp.c
@@ -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;
+}
diff --git a/src/cmd/grep/grep.h b/src/cmd/grep/grep.h
new file mode 100644
index 00000000..8445df54
--- /dev/null
+++ b/src/cmd/grep/grep.h
@@ -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*, ...);
diff --git a/src/cmd/grep/grep.y b/src/cmd/grep/grep.y
new file mode 100644
index 00000000..94a744cf
--- /dev/null
+++ b/src/cmd/grep/grep.y
@@ -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;
+}
diff --git a/src/cmd/grep/main.c b/src/cmd/grep/main.c
new file mode 100644
index 00000000..f2a6e040
--- /dev/null
+++ b/src/cmd/grep/main.c
@@ -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;
+}
diff --git a/src/cmd/grep/mkfile b/src/cmd/grep/mkfile
new file mode 100644
index 00000000..fd17abdd
--- /dev/null
+++ b/src/cmd/grep/mkfile
@@ -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
diff --git a/src/cmd/grep/sub.c b/src/cmd/grep/sub.c
new file mode 100644
index 00000000..be2acee3
--- /dev/null
+++ b/src/cmd/grep/sub.c
@@ -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");
+}
diff --git a/src/cmd/mkfile b/src/cmd/mkfile
index 3ad7ea7a..292c051b 100644
--- a/src/cmd/mkfile
+++ b/src/cmd/mkfile
@@ -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
diff --git a/src/cmd/plumb/fsys.c b/src/cmd/plumb/fsys.c
index 4776d127..33a4458e 100644
--- a/src/cmd/plumb/fsys.c
+++ b/src/cmd/plumb/fsys.c
@@ -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;
diff --git a/src/cmd/plumb/plumber.c b/src/cmd/plumb/plumber.c
index 80a57af3..bf7afa3f 100644
--- a/src/cmd/plumb/plumber.c
+++ b/src/cmd/plumb/plumber.c
@@ -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");
- plumbfile = estrdup(buf);
+ if(access(buf, 0) >= 0)
+ plumbfile = estrdup(buf);
+ else
+ plumbfile = unsharp("#9/plumb/initial.plumbing");
}
fd = open(plumbfile, OREAD);
diff --git a/src/cmd/plumb/rules.c b/src/cmd/plumb/rules.c
index 689edf59..ab27787d 100644
--- a/src/cmd/plumb/rules.c
+++ b/src/cmd/plumb/rules.c
@@ -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)
diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c
index eb93a4f5..6b32a227 100644
--- a/src/cmd/rc/plan9ish.c
+++ b/src/cmd/rc/plan9ish.c
@@ -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);
diff --git a/src/cmd/rio/Imakefile b/src/cmd/rio/Imakefile
new file mode 100644
index 00000000..43a78931
--- /dev/null
+++ b/src/cmd/rio/Imakefile
@@ -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
+
diff --git a/src/cmd/rio/color.c b/src/cmd/rio/color.c
index 8c534660..0e3c8d89 100644
--- a/src/cmd/rio/color.c
+++ b/src/cmd/rio/color.c
@@ -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;
diff --git a/src/cmd/rio/main.c b/src/cmd/rio/main.c
index 0953f1bd..02929773 100644
--- a/src/cmd/rio/main.c
+++ b/src/cmd/rio/main.c
@@ -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));
}
diff --git a/src/cmd/rio/mkfile b/src/cmd/rio/mkfile
index 8881190c..b5e8b110 100644
--- a/src/cmd/rio/mkfile
+++ b/src/cmd/rio/mkfile
@@ -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
+
+
diff --git a/src/cmd/spell/sprog.c b/src/cmd/spell/sprog.c
index e63fbb87..8d5519ef 100644
--- a/src/cmd/spell/sprog.c
+++ b/src/cmd/spell/sprog.c
@@ -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++)
diff --git a/src/cmd/yacc.c b/src/cmd/yacc.c
index 0ff114bd..6614414d 100644
--- a/src/cmd/yacc.c
+++ b/src/cmd/yacc.c
@@ -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);
diff --git a/src/lib9/_p9translate.c b/src/lib9/_p9translate.c
index 4eb6eac9..84cd65ca 100644
--- a/src/lib9/_p9translate.c
+++ b/src/lib9/_p9translate.c
@@ -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);
diff --git a/src/lib9/access.c b/src/lib9/access.c
deleted file mode 100644
index 20b00c32..00000000
--- a/src/lib9/access.c
+++ /dev/null
@@ -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;
-}
diff --git a/src/lib9/announce.c b/src/lib9/announce.c
index 9f07bd22..8fdf1d40 100644
--- a/src/lib9/announce.c
+++ b/src/lib9/announce.c
@@ -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);
diff --git a/src/lib9/create.c b/src/lib9/create.c
index bdad5f6a..97f6e7e2 100644
--- a/src/lib9/create.c
+++ b/src/lib9/create.c
@@ -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;
}
diff --git a/src/lib9/ctime.c b/src/lib9/ctime.c
index e9d971bf..0782d099 100644
--- a/src/lib9/ctime.c
+++ b/src/lib9/ctime.c
@@ -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;
diff --git a/src/lib9/date.c b/src/lib9/date.c
index 8ece0c68..8f852de2 100644
--- a/src/lib9/date.c
+++ b/src/lib9/date.c
@@ -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
diff --git a/src/lib9/dirread.c b/src/lib9/dirread.c
index aef0102f..0a72d62e 100644
--- a/src/lib9/dirread.c
+++ b/src/lib9/dirread.c
@@ -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;
diff --git a/src/lib9/errstr.c b/src/lib9/errstr.c
index 0c6ab315..578f4895 100644
--- a/src/lib9/errstr.c
+++ b/src/lib9/errstr.c
@@ -5,9 +5,10 @@
* okay.
*/
+#include <u.h>
#include <errno.h>
#include <string.h>
-#include <lib9.h>
+#include <libc.h>
enum
{
diff --git a/src/lib9/ffork-OpenBSD.c b/src/lib9/ffork-OpenBSD.c
new file mode 100644
index 00000000..5e677f72
--- /dev/null
+++ b/src/lib9/ffork-OpenBSD.c
@@ -0,0 +1 @@
+#include "ffork-pthread.c"
diff --git a/src/lib9/getuser.c b/src/lib9/getuser.c
index b53a3892..09c07041 100644
--- a/src/lib9/getuser.c
+++ b/src/lib9/getuser.c
@@ -1,6 +1,5 @@
-#include <pwd.h>
-
#include <u.h>
+#include <pwd.h>
#include <libc.h>
char*
diff --git a/src/lib9/lock.c b/src/lib9/lock.c
index 5d6f2f3e..e97b967f 100644
--- a/src/lib9/lock.c
+++ b/src/lib9/lock.c
@@ -1,6 +1,7 @@
+#include <u.h>
#include <unistd.h>
#include <sched.h>
-#include <lib9.h>
+#include <libc.h>
int _ntas;
static int
diff --git a/src/lib9/mallocz.c b/src/lib9/mallocz.c
index c6313008..a3e91510 100644
--- a/src/lib9/mallocz.c
+++ b/src/lib9/mallocz.c
@@ -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)
diff --git a/src/lib9/mkfile b/src/lib9/mkfile
index d388d224..4dda2e19 100644
--- a/src/lib9/mkfile
+++ b/src/lib9/mkfile
@@ -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\
diff --git a/src/lib9/notify.c b/src/lib9/notify.c
index 2e589de7..4d2a79ef 100644
--- a/src/lib9/notify.c
+++ b/src/lib9/notify.c
@@ -1,6 +1,5 @@
-#include <signal.h>
-
#include <u.h>
+#include <signal.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include "9proc.h"
diff --git a/src/lib9/open.c b/src/lib9/open.c
index bb597e8f..0356a7da 100644
--- a/src/lib9/open.c
+++ b/src/lib9/open.c
@@ -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;
}
diff --git a/src/lib9/rendez-Linux.c b/src/lib9/rendez-Linux.c
index 05c52ae7..673818e0 100644
--- a/src/lib9/rendez-Linux.c
+++ b/src/lib9/rendez-Linux.c
@@ -1 +1,3 @@
+/* Could use futex(2) here instead of signals? */
+
#include "rendez-signal.c"
diff --git a/src/lib9/rendez-OpenBSD.c b/src/lib9/rendez-OpenBSD.c
new file mode 100644
index 00000000..05c52ae7
--- /dev/null
+++ b/src/lib9/rendez-OpenBSD.c
@@ -0,0 +1 @@
+#include "rendez-signal.c"
diff --git a/src/lib9/rendez-pthread.c b/src/lib9/rendez-pthread.c
index b4b95f21..fe930cef 100644
--- a/src/lib9/rendez-pthread.c
+++ b/src/lib9/rendez-pthread.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
{
diff --git a/src/lib9/time.c b/src/lib9/time.c
index 169a82f5..36706367 100644
--- a/src/lib9/time.c
+++ b/src/lib9/time.c
@@ -1,7 +1,7 @@
+#include <u.h>
#include <sys/time.h>
+#include <time.h>
#include <sys/resource.h>
-
-#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c
index a359327b..05370eac 100644
--- a/src/libdraw/openfont.c
+++ b/src/libdraw/openfont.c
@@ -18,8 +18,10 @@ openfont(Display *d, char *name)
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;
}
diff --git a/src/libdraw/x11-init.c b/src/libdraw/x11-init.c
index 1283f430..c959eee4 100644
--- a/src/libdraw/x11-init.c
+++ b/src/libdraw/x11-init.c
@@ -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 */
@@ -563,6 +563,18 @@ setupcmap(XWindow w)
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()
* to translate between 24 bit X and our color. Unfortunately,
@@ -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");
diff --git a/src/libdraw/x11-itrans.c b/src/libdraw/x11-itrans.c
index 8e72b011..509b55cf 100644
--- a/src/libdraw/x11-itrans.c
+++ b/src/libdraw/x11-itrans.c
@@ -11,6 +11,9 @@
#include <keyboard.h>
#include "x11-memdraw.h"
+#undef time
+
+
static int
__xtoplan9kbd(XEvent *e)
{
diff --git a/src/libplumb/mesg.c b/src/libplumb/mesg.c
index c4094fa4..4b278695 100755
--- a/src/libplumb/mesg.c
+++ b/src/libplumb/mesg.c
@@ -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;
}
diff --git a/src/libthread/asm-OpenBSD-386.s b/src/libthread/asm-OpenBSD-386.s
new file mode 100644
index 00000000..35e2ab6f
--- /dev/null
+++ b/src/libthread/asm-OpenBSD-386.s
@@ -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
+#
diff --git a/src/libthread/exec-unix.c b/src/libthread/exec-unix.c
index bfffa14d..eb31e99e 100644
--- a/src/libthread/exec-unix.c
+++ b/src/libthread/exec-unix.c
@@ -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;
}
@@ -69,9 +71,42 @@ Bad:
}
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
diff --git a/src/libthread/label.h b/src/libthread/label.h
index 874fb070..5161e373 100644
--- a/src/libthread/label.h
+++ b/src/libthread/label.h
@@ -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;
diff --git a/src/mkfile b/src/mkfile
index 45683608..a81246cd 100644
--- a/src/mkfile
+++ b/src/mkfile
@@ -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=\