commit - cb27443abf3d6af6ab52377c71c843e619928433
commit + 8ad517944e46710ab832350c0dc3fc4e9239f7e2
blob - befea2e347dc0e8a5abfeafbfc5e904a4be5cefe
blob + 4cee8fb5f25dd82649ab4b4704dc1229dc2f5f46
--- include/fmt.h
+++ include/fmt.h
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);
blob - 1373ce1507f32799232f7be5c3997021c7c05c68
blob + 07a1f976581732cfc565e5e3fbb8ac3cbc9a6784
--- include/lib9.h
+++ 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 _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>
blob - d84870664e9f2ffcd6a93d5a6c514659645d39df
blob + 1a560b6fc51ada418265a76d3e16e9849e18d66d
--- include/libString.h
+++ include/libString.h
extern char *s_rdinstack(Sinstack*, String*);
extern Sinstack *s_allocinstack(char*);
extern void s_freeinstack(Sinstack*);
-#endif BGETC
+#endif /* BGETC */
blob - 25b042c12623573843d640fca918fcfe163e2255
blob + 64bb086743564bc4a54d5178eaa478f5f31dddd7
--- include/libc.h
+++ include/libc.h
-#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_ */
blob - e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
blob + 4716ce4f1f987092e4e103fb2b1a16685d0774c7
--- include/u.h
+++ include/u.h
+#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
blob - 8acd5524c8a8a0e49ea4267757663ebab9095dd4
blob + 644385c1a34f61006838ea6e15a16fd6770fb661
--- src/cmd/9pserve.c
+++ src/cmd/9pserve.c
}
}
-#ifdef _LIB9_H_
+#ifdef _LIBC_H_
/* unix select-based polling */
struct Ioproc
{
blob - c5a2c4244d4e5e41c372ea8b8b487447d87915e3
blob + 50c0cfc92833845183ed261eadd826ddf665eb4b
--- src/cmd/9term/9term.c
+++ src/cmd/9term/9term.c
-#include "9term.h"
+#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"
-#define fatal sysfatal
-
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 */
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 */
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);
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))
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;
mc = initmouse(nil, screen);
kc = initkeyboard(nil);
- rcstart(rcfd, argc, argv);
+ rcpid = rcstart(argc, argv, &rcfd);
hoststart();
plumbstart();
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");
a[2].op = CHANNOP;;
switch(alt(a)) {
default:
- fatal("impossible");
+ sysfatal("impossible");
case 0:
t.m = mc->m;
mouse();
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);
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
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);
plumb(t.q0, t.q1);
break;
default:
- fatal("bad menu item");
+ sysfatal("bad menu item");
}
+}
+
+int
+windfilewidth(uint q0, int oneelement)
+{
+ uint q;
+ Rune r;
+
+ q = q0;
+ while(q > 0){
+ r = t.r[q-1];
+ if(r<=' ')
+ break;
+ if(oneelement && r=='/')
+ break;
+ --q;
+ }
+ return q0-q;
}
void
+showcandidates(Completion *c)
+{
+ int i;
+ Fmt f;
+ Rune *rp;
+ uint nr, qline, q0;
+ char *s;
+
+ runefmtstrinit(&f);
+ if (c->nmatch == 0)
+ s = "[no matches in ";
+ else
+ s = "[";
+ if(c->nfile > 32)
+ fmtprint(&f, "%s%d files]\n", s, c->nfile);
+ else{
+ fmtprint(&f, "%s", s);
+ for(i=0; i<c->nfile; i++){
+ if(i > 0)
+ fmtprint(&f, " ");
+ fmtprint(&f, "%s", c->filename[i]);
+ }
+ fmtprint(&f, "]\n");
+ }
+ /* place text at beginning of line before host point */
+ qline = t.qh;
+ while(qline>0 && t.r[qline-1] != '\n')
+ qline--;
+
+ rp = runefmtstrflush(&f);
+ nr = runestrlen(rp);
+
+ q0 = t.q0;
+ q0 += insert(rp, nr, qline, 0) - qline;
+ free(rp);
+ t.q0 = q0+nr;
+ t.q1 = q0+nr;
+ updatesel();
+}
+
+Rune*
+namecomplete(void)
+{
+ int nstr, npath;
+ Rune *rp, *path, *str;
+ Completion *c;
+ char *s, *dir, *root;
+
+ /* control-f: filename completion; works back to white space or / */
+ if(t.q0<t.nr && t.r[t.q0]>' ') /* must be at end of word */
+ return nil;
+ nstr = windfilewidth(t.q0, TRUE);
+ str = runemalloc(nstr);
+ runemove(str, t.r+(t.q0-nstr), nstr);
+ npath = windfilewidth(t.q0-nstr, FALSE);
+ path = runemalloc(npath);
+ runemove(path, t.r+(t.q0-nstr-npath), npath);
+ rp = nil;
+
+ /* is path rooted? if not, we need to make it relative to window path */
+ if(npath>0 && path[0]=='/'){
+ dir = malloc(UTFmax*npath+1);
+ sprint(dir, "%.*S", npath, path);
+ }else{
+ if(strcmp(wdir, "") == 0)
+ root = ".";
+ else
+ root = wdir;
+ dir = malloc(strlen(root)+1+UTFmax*npath+1);
+ sprint(dir, "%s/%.*S", root, npath, path);
+ }
+ dir = cleanname(dir);
+
+ s = smprint("%.*S", nstr, str);
+ c = complete(dir, s);
+ free(s);
+ if(c == nil)
+ goto Return;
+
+ if(!c->advance)
+ showcandidates(c);
+
+ if(c->advance)
+ rp = runesmprint("%s", c->string);
+
+ Return:
+ freecompletion(c);
+ free(dir);
+ free(path);
+ free(str);
+ return rp;
+}
+
+void
key(Rune r)
{
- uint sig;
+ Rune *rp;
+ int nr;
if(r == 0)
return;
- if(r==SCROLLKEY){ /* scroll key */
+ switch(r){
+ case Kpgup:
+ setorigin(backnl(t.org, t.f->maxlines*2/3), 1);
+ return;
+ case Kpgdown:
setorigin(line2q(t.f->maxlines*2/3), 1);
if(t.qh<=t.org+t.f->nchars)
consread();
return;
- }else if(r == BACKSCROLLKEY){
- setorigin(backnl(t.org, t.f->maxlines*2/3), 1);
+ case Kup:
+ setorigin(backnl(t.org, t.f->maxlines/3), 1);
return;
- }else if(r == CUT){
+ case Kdown:
+ setorigin(line2q(t.f->maxlines/3), 1);
+ if(t.qh<=t.org+t.f->nchars)
+ consread();
+ return;
+ case Kleft:
+ if(t.q0 > 0){
+ t.q0--;
+ t.q1 = t.q0;
+ updatesel();
+ show(t.q0);
+ }
+ return;
+ case Kright:
+ if(t.q1 < t.nr){
+ t.q1++;
+ t.q0 = t.q1;
+ updatesel();
+ show(t.q1);
+ }
+ return;
+ case Khome:
+ show(0);
+ return;
+ case Kend:
+ case 0x05:
+ show(t.nr);
+ return;
+ case CUT:
snarf();
cut();
if(scrolling)
show(t.q0);
return;
- }else if(r == COPY){
+ case COPY:
snarf();
if(scrolling)
show(t.q0);
return;
- }else if(r == PASTE){
+ case PASTE:
snarfupdate();
paste(t.snarf, t.nsnarf, 0);
if(scrolling)
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 */
cut();
break;
default:
- Default:
paste(&r, 1, 1);
break;
}
}
/* 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(); */
}
void
runewrite(Rune *r, int n)
{
- uint m;
int i;
uint initial;
uint q0, q1;
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);
}
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);
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.
rbuf = runemalloc(n);
runemove(rbuf, r, n);
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);
}
}
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;
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);
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)
blob - 4e8d61f3887e441116c1c29fc1aa70226fc10962
blob + 57a8359e14a0285ea0f2162eb61a27a0f92175fe
--- src/cmd/9term/9term.h
+++ src/cmd/9term/9term.h
-#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[];
blob - e8b894dc83698fd802a3df51fef6c87a8d32cc60
blob + 7022d4d97bbcc6463743c5896671c5b72df537eb
--- src/cmd/9term/FreeBSD.c
+++ src/cmd/9term/FreeBSD.c
#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;
+}
+
blob - 7dd22371be723649b347508f25bcd58ac0b2a4f6
blob + 872417e6c501b8c3f1f8d0bcaba529e0f6110c67
--- src/cmd/9term/Linux.c
+++ src/cmd/9term/Linux.c
+#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;
+}
+
blob - 6a37ab337851a56a2708834897f164ae930f066c
blob + d7db9fc5de818620c1d86962c3a4befd6154d506
--- src/cmd/9term/SunOS.c
+++ src/cmd/9term/SunOS.c
#include "9term.h"
+#include <termios.h>
+#include <sys/termios.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;
-}
-
-int
getpts(int fd[], char *slave)
{
fd[1] = open("/dev/ptmx", ORDWR);
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;
+}
+
blob - d0d5ca727ee2bbde366ff4a1fe5983b5a9c0facb
blob + 8701ad9c4f21d9c76b8dbe9bbfcde00720c1c51e
--- src/cmd/9term/mkfile
+++ src/cmd/9term/mkfile
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
blob - /dev/null
blob + 7596bc41dabe45627fe6e7a63ca4a6d545bde70d (mode 644)
--- /dev/null
+++ src/cmd/9term/rcstart.c
+#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;
+}
+
blob - /dev/null
blob + a608b7edf837e9ed63229c934b86ee54be73ce8d (mode 644)
--- /dev/null
+++ src/cmd/9term/term.h
+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*);
blob - /dev/null
blob + 95d84a32fa8fb64afae6a062f45c08f989dffdb5 (mode 644)
--- /dev/null
+++ src/cmd/9term/win.c
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <fcall.h>
+#include <fs.h>
+#include "term.h"
+
+#define EVENTSIZE 256
+#define STACK 32768
+
+typedef struct Event Event;
+typedef struct Q Q;
+
+struct Event
+{
+ int c1;
+ int c2;
+ int q0;
+ int q1;
+ int flag;
+ int nb;
+ int nr;
+ char b[EVENTSIZE*UTFmax+1];
+ Rune r[EVENTSIZE+1];
+};
+
+Event blank = {
+ 'M',
+ 'X',
+ 0, 0, 0, 1, 1,
+ { ' ', 0 },
+ { ' ', 0 },
+};
+
+struct Q
+{
+ QLock lk;
+ int p;
+ int k;
+};
+
+Q q;
+
+Fid *eventfd;
+Fid *addrfd;
+Fid *datafd;
+Fid *ctlfd;
+// int bodyfd;
+
+char *typing;
+int ntypeb;
+int ntyper;
+int ntypebreak;
+int debug;
+int rcfd;
+
+char *name;
+
+char **prog;
+Channel *cwait;
+int pid = -1;
+
+int label(char*, int);
+void error(char*);
+void stdinproc(void*);
+void stdoutproc(void*);
+void type(Event*, int, Fid*, Fid*);
+void sende(Event*, int, Fid*, Fid*, Fid*, int);
+char *onestring(int, char**);
+int delete(Event*);
+void deltype(uint, uint);
+void runproc(void*);
+
+int
+fsfidprint(Fid *fid, char *fmt, ...)
+{
+ char buf[256];
+ va_list arg;
+ int n;
+
+ va_start(arg, fmt);
+ n = vsnprint(buf, sizeof buf, fmt, arg);
+ va_end(arg);
+ return fswrite(fid, buf, n);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: win cmd args...\n");
+ threadexitsall("usage");
+}
+
+int
+nopipes(void *v, char *msg)
+{
+ USED(v);
+ if(strcmp(msg, "sys: write on closed pipe") == 0)
+ return 1;
+ return 0;
+}
+
+void
+waitthread(void *v)
+{
+ recvp(cwait);
+ threadexitsall(nil);
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ int fd, id;
+ char buf[256];
+ char buf1[128];
+ Fsys *fs;
+
+ ARGBEGIN{
+ case 'd':
+ debug = 1;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ prog = argv;
+
+ if(argc > 0){
+ name = argv[0];
+ argc--;
+ argv++;
+ }else
+ name = "gnot";
+
+ threadnotify(nopipes, 1);
+ if((fs = nsmount("acme", "")) < 0)
+ sysfatal("nsmount acme: %r");
+ ctlfd = fsopen(fs, "new/ctl", ORDWR|OCEXEC);
+ if(ctlfd < 0 || fsread(ctlfd, buf, 12) != 12)
+ sysfatal("ctl: %r");
+ id = atoi(buf);
+ sprint(buf, "%d/tag", id);
+ fd = fsopenfd(fs, buf, OWRITE|OCEXEC);
+ write(fd, " Send Delete", 12);
+ close(fd);
+ sprint(buf, "%d/event", id);
+ eventfd = fsopen(fs, buf, ORDWR|OCEXEC);
+ sprint(buf, "%d/addr", id);
+ addrfd = fsopen(fs, buf, ORDWR|OCEXEC);
+ sprint(buf, "%d/data", id);
+ datafd = fsopen(fs, buf, ORDWR|OCEXEC);
+ sprint(buf, "%d/body", id);
+/* bodyfd = fsopenfd(fs, buf, ORDWR|OCEXEC); */
+ if(eventfd==nil || addrfd==nil || datafd==nil)
+ sysfatal("data files: %r");
+/*
+ if(eventfd<0 || addrfd<0 || datafd<0 || bodyfd<0)
+ sysfatal("data files: %r");
+*/
+ fsunmount(fs);
+
+ cwait = threadwaitchan();
+ threadcreate(waitthread, nil, STACK);
+ pid = rcstart(argc, argv, &rcfd);
+ if(pid == -1)
+ sysfatal("exec failed");
+
+ getwd(buf1, sizeof buf1);
+ sprint(buf, "name %s/-%s\n0\n", buf1, name);
+ fswrite(ctlfd, buf, strlen(buf));
+ sprint(buf, "dumpdir %s/\n", buf1);
+ fswrite(ctlfd, buf, strlen(buf));
+ sprint(buf, "dump %s\n", onestring(argc, argv));
+ fswrite(ctlfd, buf, strlen(buf));
+
+ threadcreate(stdoutproc, nil, STACK);
+ stdinproc(nil);
+}
+
+void
+error(char *s)
+{
+ if(s)
+ fprint(2, "win: %s: %r\n", s);
+ else
+ s = "kill";
+ if(pid != -1)
+ postnote(PNGROUP, pid, "hangup");
+ threadexitsall(s);
+}
+
+char*
+onestring(int argc, char **argv)
+{
+ char *p;
+ int i, n;
+ static char buf[1024];
+
+ if(argc == 0)
+ return "";
+ p = buf;
+ for(i=0; i<argc; i++){
+ n = strlen(argv[i]);
+ if(p+n+1 >= buf+sizeof buf)
+ break;
+ memmove(p, argv[i], n);
+ p += n;
+ *p++ = ' ';
+ }
+ p[-1] = 0;
+ return buf;
+}
+
+int
+getec(Fid *efd)
+{
+ static char buf[8192];
+ static char *bufp;
+ static int nbuf;
+
+ if(nbuf == 0){
+ nbuf = fsread(efd, buf, sizeof buf);
+ if(nbuf <= 0)
+ error(nil);
+ bufp = buf;
+ }
+ --nbuf;
+ return *bufp++;
+}
+
+int
+geten(Fid *efd)
+{
+ int n, c;
+
+ n = 0;
+ while('0'<=(c=getec(efd)) && c<='9')
+ n = n*10+(c-'0');
+ if(c != ' ')
+ error("event number syntax");
+ return n;
+}
+
+int
+geter(Fid *efd, char *buf, int *nb)
+{
+ Rune r;
+ int n;
+
+ r = getec(efd);
+ buf[0] = r;
+ n = 1;
+ if(r < Runeself)
+ goto Return;
+ while(!fullrune(buf, n))
+ buf[n++] = getec(efd);
+ chartorune(&r, buf);
+ Return:
+ *nb = n;
+ return r;
+}
+
+void
+gete(Fid *efd, Event *e)
+{
+ int i, nb;
+
+ e->c1 = getec(efd);
+ e->c2 = getec(efd);
+ e->q0 = geten(efd);
+ e->q1 = geten(efd);
+ e->flag = geten(efd);
+ e->nr = geten(efd);
+ if(e->nr > EVENTSIZE)
+ error("event string too long");
+ e->nb = 0;
+ for(i=0; i<e->nr; i++){
+ e->r[i] = geter(efd, e->b+e->nb, &nb);
+ e->nb += nb;
+ }
+ e->r[e->nr] = 0;
+ e->b[e->nb] = 0;
+ if(getec(efd) != '\n')
+ error("event syntax 2");
+}
+
+int
+nrunes(char *s, int nb)
+{
+ int i, n;
+ Rune r;
+
+ n = 0;
+ for(i=0; i<nb; n++)
+ i += chartorune(&r, s+i);
+ return n;
+}
+
+void
+stdinproc(void *v)
+{
+ Fid *cfd = ctlfd;
+ Fid *efd = eventfd;
+ Fid *dfd = datafd;
+ Fid *afd = addrfd;
+ int fd0 = rcfd;
+ Event e, e2, e3, e4;
+
+ USED(v);
+
+ for(;;){
+ if(debug)
+ fprint(2, "typing[%d,%d)\n", q.p, q.p+ntyper);
+ gete(efd, &e);
+ if(debug)
+ fprint(2, "msg %c%c q[%d,%d)... ", e.c1, e.c2, e.q0, e.q1);
+ qlock(&q.lk);
+ switch(e.c1){
+ default:
+ Unknown:
+ print("unknown message %c%c\n", e.c1, e.c2);
+ break;
+
+ case 'E': /* write to body; can't affect us */
+ if(debug)
+ fprint(2, "shift typing %d... ", e.q1-e.q0);
+ q.p += e.q1-e.q0;
+ break;
+
+ case 'F': /* generated by our actions; ignore */
+ break;
+
+ case 'K':
+ case 'M':
+ switch(e.c2){
+ case 'I':
+ if(e.q0 < q.p){
+ if(debug)
+ fprint(2, "shift typing %d... ", e.q1-e.q0);
+ q.p += e.q1-e.q0;
+ }
+ else if(e.q0 <= q.p+ntyper){
+ if(debug)
+ fprint(2, "type... ");
+ type(&e, fd0, afd, dfd);
+ }
+ break;
+
+ case 'D':
+ q.p -= delete(&e);
+ break;
+
+ case 'x':
+ case 'X':
+ if(e.flag & 2)
+ gete(efd, &e2);
+ if(e.flag & 8){
+ gete(efd, &e3);
+ gete(efd, &e4);
+ }
+ if(e.flag&1 || (e.c2=='x' && e.nr==0 && e2.nr==0)){
+ /* send it straight back */
+ fsfidprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
+ break;
+ }
+ if(e.q0==e.q1 && (e.flag&2)){
+ e2.flag = e.flag;
+ e = e2;
+ }
+ if(e.flag & 8){
+ if(e.q1 != e.q0){
+ sende(&e, fd0, cfd, afd, dfd, 0);
+ sende(&blank, fd0, cfd, afd, dfd, 0);
+ }
+ sende(&e3, fd0, cfd, afd, dfd, 1);
+ }else if(e.q1 != e.q0)
+ sende(&e, fd0, cfd, afd, dfd, 1);
+ break;
+
+ case 'l':
+ case 'L':
+ /* just send it back */
+ if(e.flag & 2)
+ gete(efd, &e2);
+ fsfidprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
+ break;
+
+ case 'd':
+ case 'i':
+ break;
+
+ default:
+ goto Unknown;
+ }
+ }
+ qunlock(&q.lk);
+ }
+}
+
+void
+stdoutproc(void *v)
+{
+ int fd1 = rcfd;
+ Fid *afd = addrfd;
+ Fid *dfd = datafd;
+ int n, m, w, npart;
+ char *buf, *s, *t;
+ Rune r;
+ char x[16], hold[UTFmax];
+
+ USED(v);
+ threadnotify(nopipes, 1);
+ 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);
+ if(n == 0)
+ continue;
+
+ /* squash NULs */
+ s = memchr(buf+npart, 0, n);
+ if(s){
+ for(t=s; s<buf+npart+n; s++)
+ if(*t = *s) /* assign = */
+ t++;
+ n = t-(buf+npart);
+ }
+
+ n += npart;
+
+ /* hold on to final partial rune */
+ npart = 0;
+ while(n>0 && (buf[n-1]&0xC0)){
+ --n;
+ npart++;
+ if((buf[n]&0xC0)!=0x80){
+ if(fullrune(buf+n, npart)){
+ w = chartorune(&r, buf+n);
+ n += w;
+ npart -= w;
+ }
+ break;
+ }
+ }
+ if(n > 0){
+ memmove(hold, buf+n, npart);
+ buf[n] = 0;
+ n = label(buf, n);
+ buf[n] = 0;
+ qlock(&q.lk);
+ m = sprint(x, "#%d", q.p);
+ if(fswrite(afd, x, m) != m)
+ error("stdout writing address");
+ if(fswrite(dfd, buf, n) != n)
+ error("stdout writing body");
+ q.p += nrunes(buf, n);
+ qunlock(&q.lk);
+ memmove(buf, hold, npart);
+ }
+ }
+}
+
+char wdir[256];
+int
+label(char *sr, int n)
+{
+ char *sl, *el, *er, *r;
+
+ er = sr+n;
+ for(r=er-1; r>=sr; r--)
+ if(*r == '\007')
+ break;
+ if(r < sr)
+ return n;
+
+ el = r+1;
+ if(el-sr > sizeof wdir)
+ sr = el - sizeof wdir;
+ for(sl=el-3; sl>=sr; sl--)
+ if(sl[0]=='\033' && sl[1]==']' && sl[2]==';')
+ break;
+ if(sl < sr)
+ return n;
+
+ *r = 0;
+ snprint(wdir, sizeof wdir, "name %s/-%s\n0\n", sl+3, name);
+ fswrite(ctlfd, wdir, strlen(wdir));
+
+ memmove(sl, el, er-el);
+ n -= (el-sl);
+ return n;
+}
+
+int
+delete(Event *e)
+{
+ uint q0, q1;
+ int deltap;
+
+ q0 = e->q0;
+ q1 = e->q1;
+ if(q1 <= q.p)
+ return e->q1-e->q0;
+ if(q0 >= q.p+ntyper)
+ return 0;
+ deltap = 0;
+ if(q0 < q.p){
+ deltap = q.p-q0;
+ q0 = 0;
+ }else
+ q0 -= q.p;
+ if(q1 > q.p+ntyper)
+ q1 = ntyper;
+ else
+ q1 -= q.p;
+ deltype(q0, q1);
+ return deltap;
+}
+
+void
+addtype(int c, uint p0, char *b, int nb, int nr)
+{
+ int i, w;
+ Rune r;
+ uint p;
+ char *b0;
+
+ for(i=0; i<nb; i+=w){
+ w = chartorune(&r, b+i);
+ if((r==0x7F||r==3) && c=='K'){
+ write(rcfd, "\x7F", 1);
+ /* toss all typing */
+ q.p += ntyper+nr;
+ ntypebreak = 0;
+ ntypeb = 0;
+ ntyper = 0;
+ /* buglet: more than one delete ignored */
+ return;
+ }
+ if(r=='\n' || r==0x04)
+ ntypebreak++;
+ }
+ typing = realloc(typing, ntypeb+nb);
+ if(typing == nil)
+ error("realloc");
+ if(p0 == ntyper)
+ memmove(typing+ntypeb, b, nb);
+ else{
+ b0 = typing;
+ for(p=0; p<p0 && b0<typing+ntypeb; p++){
+ w = chartorune(&r, b0+i);
+ b0 += w;
+ }
+ if(p != p0)
+ error("typing: findrune");
+ memmove(b0+nb, b0, (typing+ntypeb)-b0);
+ memmove(b0, b, nb);
+ }
+ ntypeb += nb;
+ ntyper += nr;
+}
+
+void
+sendtype(int fd0)
+{
+ int i, n, nr;
+
+ while(ntypebreak){
+ for(i=0; i<ntypeb; i++)
+ if(typing[i]=='\n' || typing[i]==0x04){
+ n = i + (typing[i] == '\n');
+ i++;
+ if(write(fd0, typing, n) != n)
+ error("sending to program");
+ nr = nrunes(typing, i);
+ q.p += nr;
+ ntyper -= nr;
+ ntypeb -= i;
+ memmove(typing, typing+i, ntypeb);
+ ntypebreak--;
+ goto cont2;
+ }
+ print("no breakchar\n");
+ ntypebreak = 0;
+cont2:;
+ }
+}
+
+void
+deltype(uint p0, uint p1)
+{
+ int w;
+ uint p, b0, b1;
+ Rune r;
+
+ /* advance to p0 */
+ b0 = 0;
+ for(p=0; p<p0 && b0<ntypeb; p++){
+ w = chartorune(&r, typing+b0);
+ b0 += w;
+ }
+ if(p != p0)
+ error("deltype 1");
+ /* advance to p1 */
+ b1 = b0;
+ for(; p<p1 && b1<ntypeb; p++){
+ w = chartorune(&r, typing+b1);
+ b1 += w;
+ if(r=='\n' || r==0x04)
+ ntypebreak--;
+ }
+ if(p != p1)
+ error("deltype 2");
+ memmove(typing+b0, typing+b1, ntypeb-b1);
+ ntypeb -= b1-b0;
+ ntyper -= p1-p0;
+}
+
+void
+type(Event *e, int fd0, Fid *afd, Fid *dfd)
+{
+ int m, n, nr;
+ char buf[128];
+
+ if(e->nr > 0)
+ addtype(e->c1, e->q0-q.p, e->b, e->nb, e->nr);
+ else{
+ m = e->q0;
+ while(m < e->q1){
+ n = sprint(buf, "#%d", m);
+ fswrite(afd, buf, n);
+ n = fsread(dfd, buf, sizeof buf);
+ nr = nrunes(buf, n);
+ while(m+nr > e->q1){
+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
+ --nr;
+ }
+ if(n == 0)
+ break;
+ addtype(e->c1, m-q.p, buf, n, nr);
+ m += nr;
+ }
+ }
+ sendtype(fd0);
+}
+
+void
+sende(Event *e, int fd0, Fid *cfd, Fid *afd, Fid *dfd, int donl)
+{
+ int l, m, n, nr, lastc, end;
+ char abuf[16], buf[128];
+
+ end = q.p+ntyper;
+ l = sprint(abuf, "#%d", end);
+ fswrite(afd, abuf, l);
+ if(e->nr > 0){
+ fswrite(dfd, e->b, e->nb);
+ addtype(e->c1, ntyper, e->b, e->nb, e->nr);
+ lastc = e->r[e->nr-1];
+ }else{
+ m = e->q0;
+ lastc = 0;
+ while(m < e->q1){
+ n = sprint(buf, "#%d", m);
+ fswrite(afd, buf, n);
+ n = fsread(dfd, buf, sizeof buf);
+ nr = nrunes(buf, n);
+ while(m+nr > e->q1){
+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
+ --nr;
+ }
+ if(n == 0)
+ break;
+ l = sprint(abuf, "#%d", end);
+ fswrite(afd, abuf, l);
+ fswrite(dfd, buf, n);
+ addtype(e->c1, ntyper, buf, n, nr);
+ lastc = buf[n-1];
+ m += nr;
+ end += nr;
+ }
+ }
+ if(donl && lastc!='\n'){
+ fswrite(dfd, "\n", 1);
+ addtype(e->c1, ntyper, "\n", 1, 1);
+ }
+ fswrite(cfd, "dot=addr", 8);
+ sendtype(fd0);
+}
blob - d4b4cad83e152a40020d96e612c506e031dab5bf
blob + 9636beab1bb66efaf56d803295ed0d052c0100f1
--- src/cmd/acme/acme.c
+++ src/cmd/acme/acme.c
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");
}
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;
winlock(t->w, 'K');
wincommit(t->w, t);
winunlock(t->w);
- flushwarnings(1);
flushimage(display, 1);
}
alts[KTimer].c = nil;
}
if(nbrecv(keyboardctl->c, &r) > 0)
goto casekeyboard;
- flushwarnings(1);
flushimage(display, 1);
break;
}
Plumbmsg *pm;
Mouse m;
char *act;
- enum { MResize, MMouse, MPlumb, NMALT };
+ enum { MResize, MMouse, MPlumb, MWarnings, NMALT };
static Alt alts[NMALT+1];
USED(v);
alts[MPlumb].c = cplumb;
alts[MPlumb].v = ±
alts[MPlumb].op = CHANRCV;
+ alts[MWarnings].c = cwarn;
+ alts[MWarnings].v = nil;
+ alts[MWarnings].op = CHANRCV;
if(cplumb == nil)
alts[MPlumb].op = CHANNOP;
alts[NMALT].op = CHANEND;
for(;;){
+ qlock(&row.lk);
+ flushwarnings();
+ qunlock(&row.lk);
+ flushimage(display, 1);
switch(alt(alts)){
case MResize:
if(getwindow(display, Refnone) < 0)
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){
else if(strcmp(act, "showdata")==0)
plumbshow(pm);
}
- flushwarnings(1);
- flushimage(display, 1);
- plumbfree(pm);
+ plumbfree(pm);
break;
+ case MWarnings:
+ break;
case MMouse:
/*
* Make a copy so decisions are consistent; mousectl changes
goto Continue;
}
Continue:
- flushwarnings(0);
- flushimage(display, 1);
qunlock(&row.lk);
break;
}
blob - 94cfa38314bd8e724ad7924f39c662e171407604
blob + 338a1ff8ca054a81a9f15302314472f0467d0876
--- src/cmd/acme/dat.h
+++ src/cmd/acme/dat.h
Channel *cexit; /* chan(int) */
Channel *cerr; /* chan(char*) */
Channel *cedit; /* chan(int) */
+Channel *cwarn; /* chan(void*)[1] (really chan(unit)[1]) */
#define STACK 32768
blob - 0dfae90a11fd9952836e9fb0e0ff28dbe9ff0cb6
blob + 7ccb9427291d83264fb5b72f58febf03d6d87cb3
--- src/cmd/acme/ecmd.c
+++ src/cmd/acme/ecmd.c
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){
blob - 74f9f47ced2be1ef35faca6300f8ec6837e8276f
blob + 0e3389d627b1d0cb7c27b4b0b33caa8dfdaabee2
--- src/cmd/acme/exec.c
+++ src/cmd/acme/exec.c
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);
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 };
{ 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 },
goto Fail;
Hard:
-
/*
* ugly: set path = (. $cputype /bin)
* should honor $path if unusual.
blob - 9fba7d7ad79ec07cd4e8ee6de84a0b62b65b0626
blob + c164bb3b50755773e3c3e2c6b38168a8d0611d81
--- src/cmd/acme/fns.h
+++ src/cmd/acme/fns.h
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);
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))
blob - f178f864977513bfc7ca4175b7ce6d449383b8cb
blob + af4255c8af359c8647a591be9f3f7cdc1a05acb8
--- src/cmd/acme/fsys.c
+++ src/cmd/acme/fsys.c
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";
int p[2];
char *u;
+ initfcall();
if(pipe(p) < 0)
error("can't create pipe");
if(post9pservice(p[0], "acme") < 0)
}
void
+fsysincid(Mntdir *m)
+{
+ qlock(&mnt.lk);
+ m->ref++;
+ qunlock(&mnt.lk);
+}
+
+void
fsysdelid(Mntdir *idm)
{
Mntdir *m, *prev;
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));
}
blob - f6c4d4ee5c8abff98f844c983e6dd1aae1463954
blob + 7023382677f9f931f0a5025fcfb1e13de16c3983
--- src/cmd/acme/look.c
+++ src/cmd/acme/look.c
}
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);
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;
return file;
Rescue:
- return (Runestr){r, n};
+ return runestr(r, n);
}
Runestr
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;
blob - 8bdf0b78c5cca413f6a7f4381490db61ab81262a
blob + c0cd7ec150e41361dff3593adeadd1f6b27528d7
--- src/cmd/acme/text.c
+++ src/cmd/acme/text.c
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)){
blob - de71107a5215298b0f46040b6779e55c060c97e6
blob + a7307e0665ecd8b8f81d4216042ccba7fc4950ca
--- src/cmd/acme/util.c
+++ src/cmd/acme/util.c
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)
{
}
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;
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);
winunlock(w);
bufclose(&warn->buf);
next = warn->next;
+ if(warn->md)
+ fsysdelid(warn->md);
free(warn);
}
warnings = nil;
- if(dolock)
- qunlock(&row.lk);
}
void
blob - b3bef2cd51f648934d4cd4728a211bccefb01dc4
blob + 839308eee1f3a485087ebb2a4b961be738fea8e8
--- src/cmd/acme/xfid.c
+++ src/cmd/acme/xfid.c
}
if(w)
winunlock(w);
- flushwarnings(1);
}
void
qunlock(&row.lk);
goto Rescue;
}
- flushwarnings(0);
qunlock(&row.lk);
}
b[n++] = '\n';
}
}
- flushwarnings(0);
qunlock(&row.lk);
off = x->fcall.offset;
cnt = x->fcall.count;
blob - 8cbf6aac077348accfa714b9d871c472b25009f9
blob + a3ddd890c606e526e29a48d967e2d7675718d955
--- src/cmd/dict/dict.c
+++ src/cmd/dict/dict.c
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);
blob - 8e56765fa12bc6e937f89a7b89919d6f218a7919
blob + c809ae81345741acd7d0bc5886606404cb033ba6
--- src/cmd/diff/diff.h
+++ src/cmd/diff/diff.h
+#define stdout bstdout
+
char mode; /* '\0', 'e', 'f', 'h' */
char bflag; /* ignore multiple and trailing blanks */
char rflag; /* recurse down directory trees */
blob - 43eb6dd1c4821af23b1924d1ef4a0154ef0980fe
blob + 00f69a3ec78788334760781c74263cb0e47c05ac
--- src/cmd/diff/main.c
+++ src/cmd/diff/main.c
done(int status)
{
rmtmpfiles();
+Bflush(&stdout);
+Bterm(&stdout);
switch(status)
{
case 0:
blob - f3acfca22cac1dfab9881af5c8d5e4f90cd8b47f
blob + 4aa895fec4d0f21d530c4e58a2ec9d76a56cd616
--- src/cmd/fortune.c
+++ src/cmd/fortune.c
#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
Dir *fbuf, *ixbuf;
Biobuf *f, g;
+ index = unsharp(index);
+ fortunes = unsharp(index);
+
newindex = 0;
oldindex = 0;
ix = offs = 0;
}
}
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);
blob - /dev/null
blob + 4a3f3e8f4f80ce77a3caea6b83bb546d3d3296df (mode 644)
--- /dev/null
+++ src/cmd/grep/comp.c
+#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;
+}
blob - /dev/null
blob + 8445df54a53ffbe2ecb74e2e5fafb2ff7be9a992 (mode 644)
--- /dev/null
+++ src/cmd/grep/grep.h
+#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*, ...);
blob - /dev/null
blob + 94a744cf96931a2244c69961b0b5f1c5c74f339d (mode 644)
--- /dev/null
+++ src/cmd/grep/grep.y
+%{
+#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;
+}
blob - /dev/null
blob + f2a6e040465890d6aef6cb0a21680cd65b70f143 (mode 644)
--- /dev/null
+++ src/cmd/grep/main.c
+#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;
+}
blob - /dev/null
blob + fd17abdd08f5e050fbf90d8d0f55912aa62e9814 (mode 644)
--- /dev/null
+++ src/cmd/grep/mkfile
+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
blob - /dev/null
blob + be2acee35846f9908f2d1e11f26b9a57508f6974 (mode 644)
--- /dev/null
+++ src/cmd/grep/sub.c
+#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");
+}
blob - 3ad7ea7a99c444c1502a21d18c3da4b6cb8f9339
blob + 292c051be4bb8679de5007ddbb5a58b09c3e0f5b
--- src/cmd/mkfile
+++ src/cmd/mkfile
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
blob - 4776d1278a28a6102a5bbc3689489f14c0244311
blob + 33a4458e04b0f86655b4106c7c84c40eb26fa856
--- src/cmd/plumb/fsys.c
+++ src/cmd/plumb/fsys.c
static int ndir = NQID;
static int srvfd;
+#define clock plumbclock /* SunOS name clash */
static int clock;
static Fid *fids[Nhash];
static QLock readlock;
blob - 80a57af3ee40e134770b1f70576ceb9cbc2fca67
blob + bf7afa3f80f128e820e1c1665c18009b9b2c92c7
--- src/cmd/plumb/plumber.c
+++ src/cmd/plumb/plumber.c
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);
blob - 689edf5983b22367e7c99e2946f3d7b1a8bb1fc2
blob + ab27787d670cd4dfcfcc7b4e69f89cb8101c38ee
--- src/cmd/plumb/rules.c
+++ src/cmd/plumb/rules.c
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)
blob - eb93a4f5280d82b0e65ba73d76180f4eff03644c
blob + 6b32a2277c2a9f9d09e6f9bb5c47e9e2dfed3a23
--- src/cmd/rc/plan9ish.c
+++ src/cmd/rc/plan9ish.c
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);
blob - /dev/null
blob + 43a789318cdba6a358d75ecb3643e16167ea2a5e (mode 644)
--- /dev/null
+++ src/cmd/rio/Imakefile
+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
+
blob - 8c5346601466149f832202c4647d0d3e82190e71
blob + 0e3c8d89d49b5875b786f67b13ae3f8e79d32ef1
--- src/cmd/rio/color.c
+++ src/cmd/rio/color.c
#include "fns.h"
unsigned long
-colorpixel(Display *dpy, int depth, ulong rgb)
+colorpixel(Display *dpy, int depth, unsigned long rgb)
{
int r, g, b;
blob - 0953f1bded98082226ed3e0157f505e119d3797c
blob + 029297735066658d059295bd595e63279b159437
--- src/cmd/rio/main.c
+++ src/cmd/rio/main.c
#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"
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++)
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));
}
blob - 8881190c78b5285c442cb9f2d3aba398a344c416
blob + b5e8b11098ad1aa6743b6f0373853af1b4c931fe
--- src/cmd/rio/mkfile
+++ src/cmd/rio/mkfile
+PLAN9=../../..
<$PLAN9/src/mkhdr
OFILES=\
LDFLAGS=-L$X11/lib -lXext -lX11
<$PLAN9/src/mkone
+
+CFLAGS=$CFLAGS -DSHAPE -I$X11/include
+
+
blob - e63fbb8705a5c6b413801ff46c0ac7fac81a6cf2
blob + 8d5519efc32b6cf8e0241295c7b207ca5ae43b37
--- src/cmd/spell/sprog.c
+++ src/cmd/spell/sprog.c
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++)
blob - 7f15f0578886b4bae6df95e1678624a817b82c4d (mode 644)
blob + /dev/null
--- src/cmd/win.c
+++ /dev/null
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include <fs.h>
-
-#define EVENTSIZE 256
-#define STACK 32768
-
-typedef struct Event Event;
-typedef struct Q Q;
-
-struct Event
-{
- int c1;
- int c2;
- int q0;
- int q1;
- int flag;
- int nb;
- int nr;
- char b[EVENTSIZE*UTFmax+1];
- Rune r[EVENTSIZE+1];
-};
-
-Event blank = {
- 'M',
- 'X',
- 0, 0, 0, 1, 1,
- { ' ', 0 },
- { ' ', 0 },
-};
-
-struct Q
-{
- QLock lk;
- int p;
- int k;
-};
-
-Q q;
-
-Fid *eventfd;
-Fid *addrfd;
-Fid *datafd;
-Fid *ctlfd;
-// int bodyfd;
-
-char *typing;
-int ntypeb;
-int ntyper;
-int ntypebreak;
-int debug;
-char *name;
-
-char **prog;
-int p[2];
-Channel *cpid;
-Channel *cwait;
-int pid = -1;
-
-int label(char*, int);
-void error(char*);
-void stdinproc(void*);
-void stdoutproc(void*);
-void type(Event*, int, Fid*, Fid*);
-void sende(Event*, int, Fid*, Fid*, Fid*, int);
-char *onestring(int, char**);
-int delete(Event*);
-void deltype(uint, uint);
-void runproc(void*);
-
-int
-fsfidprint(Fid *fid, char *fmt, ...)
-{
- char buf[256];
- va_list arg;
- int n;
-
- va_start(arg, fmt);
- n = vsnprint(buf, sizeof buf, fmt, arg);
- va_end(arg);
- return fswrite(fid, buf, n);
-}
-
-void
-usage(void)
-{
- fprint(2, "usage: win cmd args...\n");
- threadexitsall("usage");
-}
-
-int
-nopipes(void *v, char *msg)
-{
- USED(v);
- if(strcmp(msg, "sys: write on closed pipe") == 0)
- return 1;
- return 0;
-}
-
-void
-waitthread(void *v)
-{
- recvp(cwait);
- threadexitsall(nil);
-}
-
-void
-threadmain(int argc, char **argv)
-{
- int fd, id;
- char buf[256];
- char buf1[128];
- Fsys *fs;
-
- ARGBEGIN{
- case 'd':
- debug = 1;
- break;
- default:
- usage();
- }ARGEND
-
- prog = argv;
-
- if(argc > 0)
- name = argv[0];
- else
- name = "gnot";
-
- threadnotify(nopipes, 1);
- if((fs = nsmount("acme", "")) < 0)
- sysfatal("nsmount acme: %r");
- ctlfd = fsopen(fs, "new/ctl", ORDWR|OCEXEC);
- if(ctlfd < 0 || fsread(ctlfd, buf, 12) != 12)
- sysfatal("ctl: %r");
- id = atoi(buf);
- sprint(buf, "%d/tag", id);
- fd = fsopenfd(fs, buf, OWRITE|OCEXEC);
- write(fd, " Send Delete", 12);
- close(fd);
- sprint(buf, "%d/event", id);
- eventfd = fsopen(fs, buf, ORDWR|OCEXEC);
- sprint(buf, "%d/addr", id);
- addrfd = fsopen(fs, buf, ORDWR|OCEXEC);
- sprint(buf, "%d/data", id);
- datafd = fsopen(fs, buf, ORDWR|OCEXEC);
- sprint(buf, "%d/body", id);
-/* bodyfd = fsopenfd(fs, buf, ORDWR|OCEXEC); */
- if(eventfd==nil || addrfd==nil || datafd==nil)
- sysfatal("data files: %r");
-/*
- if(eventfd<0 || addrfd<0 || datafd<0 || bodyfd<0)
- sysfatal("data files: %r");
-*/
- 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);
- if(pid == -1)
- sysfatal("exec failed");
-
- getwd(buf1, sizeof buf1);
- sprint(buf, "name %s/-%s\n0\n", buf1, name);
- fswrite(ctlfd, buf, strlen(buf));
- sprint(buf, "dumpdir %s/\n", buf1);
- fswrite(ctlfd, buf, strlen(buf));
- sprint(buf, "dump %s\n", onestring(argc, argv));
- fswrite(ctlfd, buf, strlen(buf));
-
- threadcreate(stdoutproc, nil, STACK);
- 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)
-{
- if(s)
- fprint(2, "win: %s: %r\n", s);
- else
- s = "kill";
- if(pid != -1)
- postnote(PNGROUP, pid, "hangup");
- threadexitsall(s);
-}
-
-char*
-onestring(int argc, char **argv)
-{
- char *p;
- int i, n;
- static char buf[1024];
-
- if(argc == 0)
- return "";
- p = buf;
- for(i=0; i<argc; i++){
- n = strlen(argv[i]);
- if(p+n+1 >= buf+sizeof buf)
- break;
- memmove(p, argv[i], n);
- p += n;
- *p++ = ' ';
- }
- p[-1] = 0;
- return buf;
-}
-
-int
-getec(Fid *efd)
-{
- static char buf[8192];
- static char *bufp;
- static int nbuf;
-
- if(nbuf == 0){
- nbuf = fsread(efd, buf, sizeof buf);
- if(nbuf <= 0)
- error(nil);
- bufp = buf;
- }
- --nbuf;
- return *bufp++;
-}
-
-int
-geten(Fid *efd)
-{
- int n, c;
-
- n = 0;
- while('0'<=(c=getec(efd)) && c<='9')
- n = n*10+(c-'0');
- if(c != ' ')
- error("event number syntax");
- return n;
-}
-
-int
-geter(Fid *efd, char *buf, int *nb)
-{
- Rune r;
- int n;
-
- r = getec(efd);
- buf[0] = r;
- n = 1;
- if(r < Runeself)
- goto Return;
- while(!fullrune(buf, n))
- buf[n++] = getec(efd);
- chartorune(&r, buf);
- Return:
- *nb = n;
- return r;
-}
-
-void
-gete(Fid *efd, Event *e)
-{
- int i, nb;
-
- e->c1 = getec(efd);
- e->c2 = getec(efd);
- e->q0 = geten(efd);
- e->q1 = geten(efd);
- e->flag = geten(efd);
- e->nr = geten(efd);
- if(e->nr > EVENTSIZE)
- error("event string too long");
- e->nb = 0;
- for(i=0; i<e->nr; i++){
- e->r[i] = geter(efd, e->b+e->nb, &nb);
- e->nb += nb;
- }
- e->r[e->nr] = 0;
- e->b[e->nb] = 0;
- if(getec(efd) != '\n')
- error("event syntax 2");
-}
-
-int
-nrunes(char *s, int nb)
-{
- int i, n;
- Rune r;
-
- n = 0;
- for(i=0; i<nb; n++)
- i += chartorune(&r, s+i);
- return n;
-}
-
-void
-stdinproc(void *v)
-{
- Fid *cfd = ctlfd;
- Fid *efd = eventfd;
- Fid *dfd = datafd;
- Fid *afd = addrfd;
- int fd0 = p[0];
- Event e, e2, e3, e4;
-
- USED(v);
-
- for(;;){
- if(debug)
- fprint(2, "typing[%d,%d)\n", q.p, q.p+ntyper);
- gete(efd, &e);
- if(debug)
- fprint(2, "msg %c%c q[%d,%d)... ", e.c1, e.c2, e.q0, e.q1);
- qlock(&q.lk);
- switch(e.c1){
- default:
- Unknown:
- print("unknown message %c%c\n", e.c1, e.c2);
- break;
-
- case 'E': /* write to body; can't affect us */
- if(debug)
- fprint(2, "shift typing %d... ", e.q1-e.q0);
- q.p += e.q1-e.q0;
- break;
-
- case 'F': /* generated by our actions; ignore */
- break;
-
- case 'K':
- case 'M':
- switch(e.c2){
- case 'I':
- if(e.q0 < q.p){
- if(debug)
- fprint(2, "shift typing %d... ", e.q1-e.q0);
- q.p += e.q1-e.q0;
- }
- else if(e.q0 <= q.p+ntyper){
- if(debug)
- fprint(2, "type... ");
- type(&e, fd0, afd, dfd);
- }
- break;
-
- case 'D':
- q.p -= delete(&e);
- break;
-
- case 'x':
- case 'X':
- if(e.flag & 2)
- gete(efd, &e2);
- if(e.flag & 8){
- gete(efd, &e3);
- gete(efd, &e4);
- }
- if(e.flag&1 || (e.c2=='x' && e.nr==0 && e2.nr==0)){
- /* send it straight back */
- fsfidprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
- break;
- }
- if(e.q0==e.q1 && (e.flag&2)){
- e2.flag = e.flag;
- e = e2;
- }
- if(e.flag & 8){
- if(e.q1 != e.q0){
- sende(&e, fd0, cfd, afd, dfd, 0);
- sende(&blank, fd0, cfd, afd, dfd, 0);
- }
- sende(&e3, fd0, cfd, afd, dfd, 1);
- }else if(e.q1 != e.q0)
- sende(&e, fd0, cfd, afd, dfd, 1);
- break;
-
- case 'l':
- case 'L':
- /* just send it back */
- if(e.flag & 2)
- gete(efd, &e2);
- fsfidprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
- break;
-
- case 'd':
- case 'i':
- break;
-
- default:
- goto Unknown;
- }
- }
- qunlock(&q.lk);
- }
-}
-
-void
-stdoutproc(void *v)
-{
- int fd1 = p[0];
- Fid *afd = addrfd;
- Fid *dfd = datafd;
- int n, m, w, npart;
- char *buf, *s, *t;
- Rune r;
- char x[16], hold[UTFmax];
-
- USED(v);
- threadnotify(nopipes, 1);
- buf = malloc(8192+UTFmax+1);
- npart = 0;
- for(;;){
- n = threadread(fd1, buf+npart, 8192);
- if(n < 0)
- error(nil);
- if(n == 0)
- continue;
-
- /* squash NULs */
- s = memchr(buf+npart, 0, n);
- if(s){
- for(t=s; s<buf+npart+n; s++)
- if(*t = *s) /* assign = */
- t++;
- n = t-(buf+npart);
- }
-
- n += npart;
-
- /* hold on to final partial rune */
- npart = 0;
- while(n>0 && (buf[n-1]&0xC0)){
- --n;
- npart++;
- if((buf[n]&0xC0)!=0x80){
- if(fullrune(buf+n, npart)){
- w = chartorune(&r, buf+n);
- n += w;
- npart -= w;
- }
- break;
- }
- }
- if(n > 0){
- memmove(hold, buf+n, npart);
- buf[n] = 0;
- n = label(buf, n);
- buf[n] = 0;
- qlock(&q.lk);
- m = sprint(x, "#%d", q.p);
- if(fswrite(afd, x, m) != m)
- error("stdout writing address");
- if(fswrite(dfd, buf, n) != n)
- error("stdout writing body");
- q.p += nrunes(buf, n);
- qunlock(&q.lk);
- memmove(buf, hold, npart);
- }
- }
-}
-
-char wdir[256];
-int
-label(char *sr, int n)
-{
- char *sl, *el, *er, *r;
-
- er = sr+n;
- for(r=er-1; r>=sr; r--)
- if(*r == '\007')
- break;
- if(r < sr)
- return n;
-
- el = r+1;
- if(el-sr > sizeof wdir)
- sr = el - sizeof wdir;
- for(sl=el-3; sl>=sr; sl--)
- if(sl[0]=='\033' && sl[1]==']' && sl[2]==';')
- break;
- if(sl < sr)
- return n;
-
- *r = 0;
- snprint(wdir, sizeof wdir, "name %s/-%s\n0\n", sl+3, name);
- fswrite(ctlfd, wdir, strlen(wdir));
-
- memmove(sl, el, er-el);
- n -= (el-sl);
- return n;
-}
-
-int
-delete(Event *e)
-{
- uint q0, q1;
- int deltap;
-
- q0 = e->q0;
- q1 = e->q1;
- if(q1 <= q.p)
- return e->q1-e->q0;
- if(q0 >= q.p+ntyper)
- return 0;
- deltap = 0;
- if(q0 < q.p){
- deltap = q.p-q0;
- q0 = 0;
- }else
- q0 -= q.p;
- if(q1 > q.p+ntyper)
- q1 = ntyper;
- else
- q1 -= q.p;
- deltype(q0, q1);
- return deltap;
-}
-
-void
-addtype(int c, uint p0, char *b, int nb, int nr)
-{
- int i, w;
- Rune r;
- uint p;
- char *b0;
-
- for(i=0; i<nb; i+=w){
- w = chartorune(&r, b+i);
- if((r==0x7F||r==3) && c=='K'){
- postnote(PNGROUP, pid, "interrupt");
- /* toss all typing */
- q.p += ntyper+nr;
- ntypebreak = 0;
- ntypeb = 0;
- ntyper = 0;
- /* buglet: more than one delete ignored */
- return;
- }
- if(r=='\n' || r==0x04)
- ntypebreak++;
- }
- typing = realloc(typing, ntypeb+nb);
- if(typing == nil)
- error("realloc");
- if(p0 == ntyper)
- memmove(typing+ntypeb, b, nb);
- else{
- b0 = typing;
- for(p=0; p<p0 && b0<typing+ntypeb; p++){
- w = chartorune(&r, b0+i);
- b0 += w;
- }
- if(p != p0)
- error("typing: findrune");
- memmove(b0+nb, b0, (typing+ntypeb)-b0);
- memmove(b0, b, nb);
- }
- ntypeb += nb;
- ntyper += nr;
-}
-
-void
-sendtype(int fd0)
-{
- int i, n, nr;
-
- while(ntypebreak){
- for(i=0; i<ntypeb; i++)
- if(typing[i]=='\n' || typing[i]==0x04){
- n = i + (typing[i] == '\n');
- i++;
- if(write(fd0, typing, n) != n)
- error("sending to program");
- nr = nrunes(typing, i);
- q.p += nr;
- ntyper -= nr;
- ntypeb -= i;
- memmove(typing, typing+i, ntypeb);
- ntypebreak--;
- goto cont2;
- }
- print("no breakchar\n");
- ntypebreak = 0;
-cont2:;
- }
-}
-
-void
-deltype(uint p0, uint p1)
-{
- int w;
- uint p, b0, b1;
- Rune r;
-
- /* advance to p0 */
- b0 = 0;
- for(p=0; p<p0 && b0<ntypeb; p++){
- w = chartorune(&r, typing+b0);
- b0 += w;
- }
- if(p != p0)
- error("deltype 1");
- /* advance to p1 */
- b1 = b0;
- for(; p<p1 && b1<ntypeb; p++){
- w = chartorune(&r, typing+b1);
- b1 += w;
- if(r=='\n' || r==0x04)
- ntypebreak--;
- }
- if(p != p1)
- error("deltype 2");
- memmove(typing+b0, typing+b1, ntypeb-b1);
- ntypeb -= b1-b0;
- ntyper -= p1-p0;
-}
-
-void
-type(Event *e, int fd0, Fid *afd, Fid *dfd)
-{
- int m, n, nr;
- char buf[128];
-
- if(e->nr > 0)
- addtype(e->c1, e->q0-q.p, e->b, e->nb, e->nr);
- else{
- m = e->q0;
- while(m < e->q1){
- n = sprint(buf, "#%d", m);
- fswrite(afd, buf, n);
- n = fsread(dfd, buf, sizeof buf);
- nr = nrunes(buf, n);
- while(m+nr > e->q1){
- do; while(n>0 && (buf[--n]&0xC0)==0x80);
- --nr;
- }
- if(n == 0)
- break;
- addtype(e->c1, m-q.p, buf, n, nr);
- m += nr;
- }
- }
- sendtype(fd0);
-}
-
-void
-sende(Event *e, int fd0, Fid *cfd, Fid *afd, Fid *dfd, int donl)
-{
- int l, m, n, nr, lastc, end;
- char abuf[16], buf[128];
-
- end = q.p+ntyper;
- l = sprint(abuf, "#%d", end);
- fswrite(afd, abuf, l);
- if(e->nr > 0){
- fswrite(dfd, e->b, e->nb);
- addtype(e->c1, ntyper, e->b, e->nb, e->nr);
- lastc = e->r[e->nr-1];
- }else{
- m = e->q0;
- lastc = 0;
- while(m < e->q1){
- n = sprint(buf, "#%d", m);
- fswrite(afd, buf, n);
- n = fsread(dfd, buf, sizeof buf);
- nr = nrunes(buf, n);
- while(m+nr > e->q1){
- do; while(n>0 && (buf[--n]&0xC0)==0x80);
- --nr;
- }
- if(n == 0)
- break;
- l = sprint(abuf, "#%d", end);
- fswrite(afd, abuf, l);
- fswrite(dfd, buf, n);
- addtype(e->c1, ntyper, buf, n, nr);
- lastc = buf[n-1];
- m += nr;
- end += nr;
- }
- }
- if(donl && lastc!='\n'){
- fswrite(dfd, "\n", 1);
- addtype(e->c1, ntyper, "\n", 1, 1);
- }
- fswrite(cfd, "dot=addr", 8);
- sendtype(fd0);
-}
blob - 0ff114bda442cba2b11264a84e65d9e8202ca6fd
blob + 6614414dffba4790fd17b8ea871f948de0fb859d
--- src/cmd/yacc.c
+++ src/cmd/yacc.c
{
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);
blob - 4eb6eac9869b53fcafbf301a4f7f596c02ceb242
blob + 84cd65caedb79829a0d3b445b7be553761f47184
--- src/lib9/_p9translate.c
+++ src/lib9/_p9translate.c
};
char*
-_p9translate(char *old)
+plan9translate(char *old)
{
char *new;
int i, olen, nlen, len;
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);
blob - 20b00c32744d1d1cf75af6196b1dbeb9b6905be9 (mode 644)
blob + /dev/null
--- src/lib9/access.c
+++ /dev/null
-#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;
-}
blob - 9f07bd2293c96907db947cf5003832c035491786
blob + 8fdf1d40c610b4826f04830e3b618a2c488f3809
--- src/lib9/announce.c
+++ src/lib9/announce.c
char *net;
u32int host;
int port, s;
- int n, sn;
+ int n;
+ socklen_t sn;
struct sockaddr_in sa;
struct sockaddr_un sun;
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);
blob - bdad5f6a0c8f8e69a6b0f594255deb43adc6ccf7
blob + 97f6e7e2a2540b09548fe7881751401c556a5b9e
--- src/lib9/create.c
+++ src/lib9/create.c
#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;
mode &= ~(ORCLOSE|OCEXEC);
if(rclose)
remove(path);
}
- if(path != xpath)
- free(path);
return fd;
}
blob - e9d971bf69d310b26e00a5fcbbfb58ab187234c7
blob + 0782d099feacdb1a59f797fa707967543f57c28a
--- src/lib9/ctime.c
+++ src/lib9/ctime.c
char*
asctime(Tm *t)
{
+ int i;
char *ncp;
static char cbuf[30];
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;
blob - 8ece0c688819408c91609118d132a62759f967de
blob + 8f852de294f80d7971852ac8da157906f3c6bce0
--- src/lib9/date.c
+++ src/lib9/date.c
-#include <stdlib.h> /* setenv etc. */
-
#include <u.h>
+#include <stdlib.h> /* setenv etc. */
#define NOPLAN9DEFINES
#include <libc.h>
#include <time.h>
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;
#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
blob - aef0102f85fae9bb11e921ee5dda0aab3aa5c018
blob + 0a72d62e4d0848176f0bd17fe7e322092faf9d4e
--- src/lib9/dirread.c
+++ src/lib9/dirread.c
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)
{
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;
blob - 0c6ab315d608390321d8864a7b77c56cb8bec82a
blob + 578f4895e7fdbe7b24abba707c414f3d8c070593
--- src/lib9/errstr.c
+++ src/lib9/errstr.c
* okay.
*/
+#include <u.h>
#include <errno.h>
#include <string.h>
-#include <lib9.h>
+#include <libc.h>
enum
{
blob - /dev/null
blob + 5e677f72e45ae45af3b3d6c6d7a744c881f99cdc (mode 644)
--- /dev/null
+++ src/lib9/ffork-OpenBSD.c
+#include "ffork-pthread.c"
blob - b53a3892ea57cc897b447af11b7fb56a53cd70dd
blob + 09c070419fcf7b0da6e424eca4f277894247243c
--- src/lib9/getuser.c
+++ src/lib9/getuser.c
-#include <pwd.h>
-
#include <u.h>
+#include <pwd.h>
#include <libc.h>
char*
blob - 5d6f2f3e154a56e67cc612b6923393708ad3197e
blob + e97b967f2076b2a9abdf07db6143571cd29d3ebe
--- src/lib9/lock.c
+++ src/lib9/lock.c
+#include <u.h>
#include <unistd.h>
#include <sched.h>
-#include <lib9.h>
+#include <libc.h>
int _ntas;
static int
blob - c631300887cd2d5adf3062f6c7e7a979717a5926
blob + a3e91510b17797b6b4287f44a601d1fc43c6806d
--- src/lib9/mallocz.c
+++ src/lib9/mallocz.c
+#include <u.h>
#include <unistd.h>
#include <string.h>
-#include <lib9.h>
+#include <libc.h>
void*
mallocz(unsigned long n, int clr)
blob - d388d224e9787a3328043b613193caede3d1ab22
blob + 4dda2e19fd25a41447294d6f63969d08d2250dba
--- src/lib9/mkfile
+++ src/lib9/mkfile
_p9dialparse.$O\
_p9dir.$O\
_p9proc.$O\
- _p9translate.$O\
- access.$O\
announce.$O\
argv0.$O\
atexit.$O\
exec.$O\
fcallfmt.$O\
ffork-$SYSNAME.$O\
+ get9root.$O\
getcallerpc-$OBJTYPE.$O\
getenv.$O\
getfields.$O\
u16.$O\
u32.$O\
u64.$O\
+ unsharp.$O\
wait.$O\
waitpid.$O\
blob - 2e589de750352136856816e158011977e6a92b2d
blob + 4d2a79efc69006750f6a0e526d2812bb09be677c
--- src/lib9/notify.c
+++ src/lib9/notify.c
-#include <signal.h>
-
#include <u.h>
+#include <signal.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include "9proc.h"
blob - bb597e8f2171fcf792f8ac5b591c0ecd5771981b
blob + 0356a7dabc561721f96dfe4fc29cab25526404ae
--- src/lib9/open.c
+++ src/lib9/open.c
#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;
werrstr("mode not supported");
return -1;
}
- if((name = _p9translate(xname)) == nil)
- return -1;
fd = open(name, umode);
if(fd >= 0){
if(cexec)
if(rclose)
remove(name);
}
- if(name != xname)
- free(name);
return fd;
}
blob - 05c52ae734310ff4b438ce004313a539c33d7723
blob + 673818e05550b72a45b9e5b1832403be53f78186
--- src/lib9/rendez-Linux.c
+++ src/lib9/rendez-Linux.c
+/* Could use futex(2) here instead of signals? */
+
#include "rendez-signal.c"
blob - /dev/null
blob + 05c52ae734310ff4b438ce004313a539c33d7723 (mode 644)
--- /dev/null
+++ src/lib9/rendez-OpenBSD.c
+#include "rendez-signal.c"
blob - b4b95f21d56fe32fe97d1de8d7014a3673eb5382
blob + fe930cef28e9cb52998b7961046f98494d43eb93
--- src/lib9/rendez-pthread.c
+++ src/lib9/rendez-pthread.c
* shared memory and mutexes.
*/
+#include <u.h>
#include <pthread.h>
#include <signal.h>
-#include <lib9.h>
+#include <libc.h>
enum
{
blob - 169a82f50287cfd9b64a4b4f9f531b96c168c517
blob + 367063678baf5c1e46c9ae06145dea695f5a1f7a
--- src/lib9/time.c
+++ src/lib9/time.c
+#include <u.h>
#include <sys/time.h>
+#include <time.h>
#include <sys/resource.h>
-
-#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
blob - a359327b598ca6382449b1d8bacfe2495f1dc61d
blob + 05370eacc95899850aaadde56bfd897dd27c6fbe
--- src/libdraw/openfont.c
+++ src/libdraw/openfont.c
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;
}
blob - 1283f430f09ef8b88ea7845511598eeb88f288d4
blob + c959eee4c98e8c7766e4758267c21a1fa2833e8c
--- src/libdraw/x11-init.c
+++ src/libdraw/x11-init.c
/*
* 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)
_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;
_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
Dx(r), /* width */
Dy(r), /* height */
0, /* border width */
- DefaultDepthOfScreen(xscreen), /* depth */
+ _x.depth, /* depth */
InputOutput, /* class */
_x.vis, /* visual */
/* valuemask */
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,
* 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");
blob - 8e72b011e66d53e9ea0a2a29a7d27f70adea3384
blob + 509b55cfca5067d01dbae74c4dce6643a9796692
--- src/libdraw/x11-itrans.c
+++ src/libdraw/x11-itrans.c
#include <keyboard.h>
#include "x11-memdraw.h"
+#undef time
+
+
static int
__xtoplan9kbd(XEvent *e)
{
blob - c4094fa485c45e39500cc4a3baabf197000bf5f9
blob + 4b2786955cb006ce47083802e184ea2b5e0348fd
--- src/libplumb/mesg.c
+++ src/libplumb/mesg.c
if(buf == nil)
return -1;
n = fswrite(fid, buf, n);
-fprint(2, "fswrite %d\n", n);
free(buf);
return n;
}
blob - /dev/null
blob + 35e2ab6f87f746e3acc9434f2e5571c0184b4145 (mode 644)
--- /dev/null
+++ src/libthread/asm-OpenBSD-386.s
+.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
+#
blob - bfffa14d4cf6a2d639605e20c9001b506748d7a7
blob + eb31e99e76c4aaa573b1722395dd610c72d4f1f5
--- src/libthread/exec-unix.c
+++ src/libthread/exec-unix.c
#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;
efork(fd, pfd, prog, args);
_exit(0);
default:
+ if(freeargs)
+ free(args);
break;
}
}
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
blob - 874fb070f5239dbf1aa1a3b58c149fe0948fc067
blob + 5161e3738095cabb3968ccd220ca0966bc6439a0
--- src/libthread/label.h
+++ src/libthread/label.h
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;
blob - 45683608e52ebb5bcf763e113846686d4af82af0
blob + a81246cd7a13b657f64e2d996a9d3708f32885cd
--- src/mkfile
+++ src/mkfile
<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=\