]> Cypherpunks.ru repositories - gostls13.git/commitdiff
import the plan 9 libraries libc (lib9) and libbio into the tree.
authorRob Pike <r@golang.org>
Thu, 12 Jun 2008 20:26:16 +0000 (13:26 -0700)
committerRob Pike <r@golang.org>
Thu, 12 Jun 2008 20:26:16 +0000 (13:26 -0700)
remove the dependency on /home/r.

SVN=122482

106 files changed:
include/bio.h [new file with mode: 0644]
include/fmt.h [new file with mode: 0644]
include/libc.h [new file with mode: 0644]
include/u.h [new file with mode: 0644]
src/clean.bash [new file with mode: 0755]
src/cmd/6a/Makefile
src/cmd/6c/Makefile
src/cmd/6g/Makefile
src/cmd/6l/Makefile
src/cmd/cc/Makefile
src/cmd/gc/Makefile
src/lib9/Makefile [new file with mode: 0644]
src/lib9/_exits.c [new file with mode: 0644]
src/lib9/_p9dir.c [new file with mode: 0644]
src/lib9/argv0.c [new file with mode: 0644]
src/lib9/atoi.c [new file with mode: 0644]
src/lib9/await.c [new file with mode: 0644]
src/lib9/cleanname.c [new file with mode: 0644]
src/lib9/create.c [new file with mode: 0644]
src/lib9/dirfstat.c [new file with mode: 0644]
src/lib9/dirfwstat.c [new file with mode: 0644]
src/lib9/dirstat.c [new file with mode: 0644]
src/lib9/dirwstat.c [new file with mode: 0644]
src/lib9/dup.c [new file with mode: 0644]
src/lib9/errstr.c [new file with mode: 0644]
src/lib9/exec.c [new file with mode: 0644]
src/lib9/execl.c [new file with mode: 0644]
src/lib9/exitcode.c [new file with mode: 0644]
src/lib9/fmt/charstod.c [new file with mode: 0644]
src/lib9/fmt/dofmt.c [new file with mode: 0644]
src/lib9/fmt/dorfmt.c [new file with mode: 0644]
src/lib9/fmt/errfmt.c [new file with mode: 0644]
src/lib9/fmt/fltfmt.c [new file with mode: 0644]
src/lib9/fmt/fmt.c [new file with mode: 0644]
src/lib9/fmt/fmtdef.h [new file with mode: 0644]
src/lib9/fmt/fmtfd.c [new file with mode: 0644]
src/lib9/fmt/fmtfdflush.c [new file with mode: 0644]
src/lib9/fmt/fmtlocale.c [new file with mode: 0644]
src/lib9/fmt/fmtlock.c [new file with mode: 0644]
src/lib9/fmt/fmtnull.c [new file with mode: 0644]
src/lib9/fmt/fmtprint.c [new file with mode: 0644]
src/lib9/fmt/fmtquote.c [new file with mode: 0644]
src/lib9/fmt/fmtrune.c [new file with mode: 0644]
src/lib9/fmt/fmtstr.c [new file with mode: 0644]
src/lib9/fmt/fmtvprint.c [new file with mode: 0644]
src/lib9/fmt/fprint.c [new file with mode: 0644]
src/lib9/fmt/nan64.c [new file with mode: 0644]
src/lib9/fmt/pow10.c [new file with mode: 0644]
src/lib9/fmt/print.c [new file with mode: 0644]
src/lib9/fmt/seprint.c [new file with mode: 0644]
src/lib9/fmt/smprint.c [new file with mode: 0644]
src/lib9/fmt/snprint.c [new file with mode: 0644]
src/lib9/fmt/sprint.c [new file with mode: 0644]
src/lib9/fmt/test.c [new file with mode: 0644]
src/lib9/fmt/vfprint.c [new file with mode: 0644]
src/lib9/fmt/vseprint.c [new file with mode: 0644]
src/lib9/fmt/vsmprint.c [new file with mode: 0644]
src/lib9/fmt/vsnprint.c [new file with mode: 0644]
src/lib9/fmtlock2.c [new file with mode: 0644]
src/lib9/fork.c [new file with mode: 0644]
src/lib9/getenv.c [new file with mode: 0644]
src/lib9/getfields.c [new file with mode: 0644]
src/lib9/getuser.c [new file with mode: 0644]
src/lib9/getwd.c [new file with mode: 0644]
src/lib9/jmp.c [new file with mode: 0644]
src/lib9/main.c [new file with mode: 0644]
src/lib9/nan.c [new file with mode: 0644]
src/lib9/notify.c [new file with mode: 0644]
src/lib9/nulldir.c [new file with mode: 0644]
src/lib9/open.c [new file with mode: 0644]
src/lib9/pipe.c [new file with mode: 0644]
src/lib9/readn.c [new file with mode: 0644]
src/lib9/rfork.c [new file with mode: 0644]
src/lib9/seek.c [new file with mode: 0644]
src/lib9/strecpy.c [new file with mode: 0644]
src/lib9/sysfatal.c [new file with mode: 0644]
src/lib9/tokenize.c [new file with mode: 0644]
src/lib9/utf/rune.c [new file with mode: 0644]
src/lib9/utf/runetype.c [new file with mode: 0644]
src/lib9/utf/utfdef.h [new file with mode: 0644]
src/lib9/utf/utfecpy.c [new file with mode: 0644]
src/lib9/utf/utflen.c [new file with mode: 0644]
src/lib9/utf/utfnlen.c [new file with mode: 0644]
src/lib9/utf/utfrrune.c [new file with mode: 0644]
src/lib9/utf/utfrune.c [new file with mode: 0644]
src/lib9/utf/utfutf.c [new file with mode: 0644]
src/libbio/Makefile [new file with mode: 0644]
src/libbio/bbuffered.c [new file with mode: 0644]
src/libbio/bfildes.c [new file with mode: 0644]
src/libbio/bflush.c [new file with mode: 0644]
src/libbio/bgetc.c [new file with mode: 0644]
src/libbio/bgetd.c [new file with mode: 0644]
src/libbio/bgetrune.c [new file with mode: 0644]
src/libbio/binit.c [new file with mode: 0644]
src/libbio/boffset.c [new file with mode: 0644]
src/libbio/bprint.c [new file with mode: 0644]
src/libbio/bputc.c [new file with mode: 0644]
src/libbio/bputrune.c [new file with mode: 0644]
src/libbio/brdline.c [new file with mode: 0644]
src/libbio/brdstr.c [new file with mode: 0644]
src/libbio/bread.c [new file with mode: 0644]
src/libbio/bseek.c [new file with mode: 0644]
src/libbio/bwrite.c [new file with mode: 0644]
src/make.bash
src/runtime/clean.bash [new file with mode: 0644]
test/golden.out

diff --git a/include/bio.h b/include/bio.h
new file mode 100644 (file)
index 0000000..a56e320
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/include/bio.h
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef _BIO_H_
+#define _BIO_H_ 1
+#if defined(__cplusplus)
+extern "C" { 
+#endif
+
+#ifdef AUTOLIB
+AUTOLIB(bio)
+#endif
+
+#include <sys/types.h> /* for off_t */
+#include <fcntl.h>     /* for O_RDONLY, O_WRONLY */
+
+typedef        struct  Biobuf  Biobuf;
+
+enum
+{
+       Bsize           = 8*1024,
+       Bungetsize      = 4,            /* space for ungetc */
+       Bmagic          = 0x314159,
+       Beof            = -1,
+       Bbad            = -2,
+
+       Binactive       = 0,            /* states */
+       Bractive,
+       Bwactive,
+       Bracteof,
+
+       Bend
+};
+
+struct Biobuf
+{
+       int     icount;         /* neg num of bytes at eob */
+       int     ocount;         /* num of bytes at bob */
+       int     rdline;         /* num of bytes after rdline */
+       int     runesize;       /* num of bytes of last getrune */
+       int     state;          /* r/w/inactive */
+       int     fid;            /* open file */
+       int     flag;           /* magic if malloc'ed */
+       off_t   offset;         /* offset of buffer in file */
+       int     bsize;          /* size of buffer */
+       unsigned char*  bbuf;           /* pointer to beginning of buffer */
+       unsigned char*  ebuf;           /* pointer to end of buffer */
+       unsigned char*  gbuf;           /* pointer to good data in buf */
+       unsigned char   b[Bungetsize+Bsize];
+};
+
+#define        BGETC(bp)\
+       ((bp)->icount?(bp)->bbuf[(bp)->bsize+(bp)->icount++]:Bgetc((bp)))
+#define        BPUTC(bp,c)\
+       ((bp)->ocount?(bp)->bbuf[(bp)->bsize+(bp)->ocount++]=(c),0:Bputc((bp),(c)))
+#define        BOFFSET(bp)\
+       (((bp)->state==Bractive)?\
+               (bp)->offset + (bp)->icount:\
+       (((bp)->state==Bwactive)?\
+               (bp)->offset + ((bp)->bsize + (bp)->ocount):\
+               -1))
+#define        BLINELEN(bp)\
+       (bp)->rdline
+#define        BFILDES(bp)\
+       (bp)->fid
+
+int    Bbuffered(Biobuf*);
+Biobuf*        Bfdopen(int, int);
+int    Bfildes(Biobuf*);
+int    Bflush(Biobuf*);
+int    Bgetc(Biobuf*);
+int    Bgetd(Biobuf*, double*);
+long   Bgetrune(Biobuf*);
+int    Binit(Biobuf*, int, int);
+int    Binits(Biobuf*, int, int, unsigned char*, int);
+int    Blinelen(Biobuf*);
+off_t  Boffset(Biobuf*);
+Biobuf*        Bopen(char*, int);
+int    Bprint(Biobuf*, char*, ...);
+int    Bputc(Biobuf*, int);
+int    Bputrune(Biobuf*, long);
+void*  Brdline(Biobuf*, int);
+char*  Brdstr(Biobuf*, int, int);
+long   Bread(Biobuf*, void*, long);
+off_t  Bseek(Biobuf*, off_t, int);
+int    Bterm(Biobuf*);
+int    Bungetc(Biobuf*);
+int    Bungetrune(Biobuf*);
+long   Bwrite(Biobuf*, void*, long);
+int    Bvprint(Biobuf*, char*, va_list);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/include/fmt.h b/include/fmt.h
new file mode 100644 (file)
index 0000000..480ccad
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef _FMT_H_
+#define _FMT_H_ 1
+#if defined(__cplusplus)
+extern "C" { 
+#endif
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <stdarg.h>
+#include <utf.h>
+
+typedef struct Fmt     Fmt;
+struct Fmt{
+       unsigned char   runes;          /* output buffer is runes or chars? */
+       void    *start;                 /* of buffer */
+       void    *to;                    /* current place in the buffer */
+       void    *stop;                  /* end of the buffer; overwritten if flush fails */
+       int     (*flush)(Fmt *);        /* called when to == stop */
+       void    *farg;                  /* to make flush a closure */
+       int     nfmt;                   /* num chars formatted so far */
+       va_list args;                   /* args passed to dofmt */
+       int     r;                      /* % format Rune */
+       int     width;
+       int     prec;
+       unsigned long   flags;
+       char    *decimal;       /* decimal point; cannot be "" */
+
+       /* For %'d */
+       char *thousands;        /* separator for thousands */
+       
+       /* 
+        * Each char is an integer indicating #digits before next separator. Values:
+        *      \xFF: no more grouping (or \x7F; defined to be CHAR_MAX in POSIX)
+        *      \x00: repeat previous indefinitely
+        *      \x**: count that many
+        */
+       char    *grouping;              /* descriptor of separator placement */
+};
+
+enum{
+       FmtWidth        = 1,
+       FmtLeft         = FmtWidth << 1,
+       FmtPrec         = FmtLeft << 1,
+       FmtSharp        = FmtPrec << 1,
+       FmtSpace        = FmtSharp << 1,
+       FmtSign         = FmtSpace << 1,
+       FmtApost                = FmtSign << 1,
+       FmtZero         = FmtApost << 1,
+       FmtUnsigned     = FmtZero << 1,
+       FmtShort        = FmtUnsigned << 1,
+       FmtLong         = FmtShort << 1,
+       FmtVLong        = FmtLong << 1,
+       FmtComma        = FmtVLong << 1,
+       FmtByte         = FmtComma << 1,
+       FmtLDouble      = FmtByte << 1,
+
+       FmtFlag         = FmtLDouble << 1
+};
+
+extern int     (*fmtdoquote)(int);
+
+/* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/fmt/?*.c | grep -v static |grep -v __ */
+int            dofmt(Fmt *f, char *fmt);
+int            dorfmt(Fmt *f, const Rune *fmt);
+double         fmtcharstod(int(*f)(void*), void *vp);
+int            fmtfdflush(Fmt *f);
+int            fmtfdinit(Fmt *f, int fd, char *buf, int size);
+int            fmtinstall(int c, int (*f)(Fmt*));
+int            fmtnullinit(Fmt*);
+void           fmtlocaleinit(Fmt*, char*, char*, char*);
+int            fmtprint(Fmt *f, char *fmt, ...);
+int            fmtrune(Fmt *f, int r);
+int            fmtrunestrcpy(Fmt *f, Rune *s);
+int            fmtstrcpy(Fmt *f, char *s);
+char*          fmtstrflush(Fmt *f);
+int            fmtstrinit(Fmt *f);
+double         fmtstrtod(const char *as, char **aas);
+int            fmtvprint(Fmt *f, char *fmt, va_list args);
+int            fprint(int fd, char *fmt, ...);
+int            print(char *fmt, ...);
+void           quotefmtinstall(void);
+int            quoterunestrfmt(Fmt *f);
+int            quotestrfmt(Fmt *f);
+Rune*          runefmtstrflush(Fmt *f);
+int            runefmtstrinit(Fmt *f);
+Rune*          runeseprint(Rune *buf, Rune *e, char *fmt, ...);
+Rune*          runesmprint(char *fmt, ...);
+int            runesnprint(Rune *buf, int len, char *fmt, ...);
+int            runesprint(Rune *buf, char *fmt, ...);
+Rune*          runevseprint(Rune *buf, Rune *e, char *fmt, va_list args);
+Rune*          runevsmprint(char *fmt, va_list args);
+int            runevsnprint(Rune *buf, int len, char *fmt, va_list args);
+char*          seprint(char *buf, char *e, char *fmt, ...);
+char*          smprint(char *fmt, ...);
+int            snprint(char *buf, int len, char *fmt, ...);
+int            sprint(char *buf, char *fmt, ...);
+int            vfprint(int fd, char *fmt, va_list args);
+char*          vseprint(char *buf, char *e, char *fmt, va_list args);
+char*          vsmprint(char *fmt, va_list args);
+int            vsnprint(char *buf, int len, char *fmt, va_list args);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/include/libc.h b/include/libc.h
new file mode 100644 (file)
index 0000000..2eceaea
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+Derived from Inferno include/kern.h and
+Plan 9 from User Space include/libc.h
+
+http://code.google.com/p/inferno-os/source/browse/include/kern.h
+http://code.swtch.com/plan9port/src/tip/include/libc.h
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+       Portions Copyright © 2001-2007 Russ Cox.  All rights reserved.
+       Portions Copyright © 2009 The Go Authors.  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/*
+ * 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
+
+#include <utf.h>
+#include <fmt.h>
+
+/*
+ * Begin trimmed down usual libc.h
+ */
+
+#ifndef nil
+#define        nil     ((void*)0)
+#endif
+#define        nelem(x)        (sizeof(x)/sizeof((x)[0]))
+
+#ifndef offsetof
+#define offsetof(s, m) (ulong)(&(((s*)0)->m))
+#endif
+
+extern char*   strecpy(char*, char*, char*);
+extern  int tokenize(char*, char**, int);
+
+extern  double  p9cputime(void);
+#ifndef NOPLAN9DEFINES
+#define cputime     p9cputime
+#endif
+/*
+ * one-of-a-kind
+ */
+enum
+{
+       PNPROC          = 1,
+       PNGROUP         = 2
+};
+int isInf(double, int);
+
+extern int     p9atoi(char*);
+extern long    p9atol(char*);
+extern vlong   p9atoll(char*);
+extern double  fmtcharstod(int(*)(void*), void*);
+extern char*   cleanname(char*);
+extern int     exitcode(char*);
+extern void    exits(char*);
+extern double  frexp(double, int*);
+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 void    p9longjmp(p9jmp_buf, int);
+extern char*   mktemp(char*);
+extern int             opentemp(char*);
+extern void    p9notejmp(void*, p9jmp_buf, int);
+extern void    perror(const char*);
+extern int     postnote(int, int, char *);
+extern double  p9pow10(int);
+extern char*   searchpath(char*);
+#define p9setjmp(b)    sigsetjmp((void*)(b), 1)
+
+extern void    sysfatal(char*, ...);
+
+#ifndef NOPLAN9DEFINES
+#define atoi           p9atoi
+#define atol           p9atol
+#define atoll          p9atoll
+#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 pow10          p9pow10
+#define strtod         fmtstrtod
+#define charstod       fmtcharstod
+#endif
+
+/*
+ * 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        ODIRECT 128     /* or'ed in, direct access */
+#define        ONONBLOCK 256   /* or'ed in, non-blocking call */
+#define        OEXCL   0x1000  /* or'ed in, exclusive use (create only) */
+#define        OLOCK   0x2000  /* or'ed in, lock after opening */
+#define        OAPPEND 0x4000  /* or'ed in, append 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 QTTMP          0x04            /* type bit for non-backed-up file */
+#define QTSYMLINK      0x02            /* type bit for symbolic link */
+#define QTFILE         0x00            /* type bits for plain file */
+
+/* bits in Dir.mode */
+#define DMDIR          0x80000000      /* mode bit for directories */
+#define DMAPPEND       0x40000000      /* mode bit for append only files */
+#define DMEXCL         0x20000000      /* mode bit for exclusive use files */
+#define DMMOUNT                0x10000000      /* mode bit for mounted channel */
+#define DMAUTH         0x08000000      /* mode bit for authentication file */
+#define DMTMP          0x04000000      /* mode bit for non-backed-up file */
+#define DMSYMLINK      0x02000000      /* mode bit for symbolic link (Unix, 9P2000.u) */
+#define DMDEVICE       0x00800000      /* mode bit for device file (Unix, 9P2000.u) */
+#define DMNAMEDPIPE    0x00200000      /* mode bit for named pipe (Unix, 9P2000.u) */
+#define DMSOCKET       0x00100000      /* mode bit for socket (Unix, 9P2000.u) */
+#define DMSETUID       0x00080000      /* mode bit for setuid (Unix, 9P2000.u) */
+#define DMSETGID       0x00040000      /* mode bit for setgid (Unix, 9P2000.u) */
+
+#define DMREAD         0x4             /* mode bit for read permission */
+#define DMWRITE                0x2             /* mode bit for write permission */
+#define DMEXEC         0x1             /* mode bit for execute permission */
+
+#ifdef RFMEM   /* FreeBSD, OpenBSD */
+#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) */
+};
+
+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 */
+
+       /* 9P2000.u extensions */
+       uint    uidnum;         /* numeric uid */
+       uint    gidnum;         /* numeric gid */
+       uint    muidnum;        /* numeric muid */
+       char    *ext;           /* extended info */
+} Dir;
+
+typedef
+struct Waitmsg
+{
+       int pid;        /* of loved one */
+       ulong time[3];  /* of loved one & descendants */
+       char    *msg;
+} Waitmsg;
+
+extern void    _exits(char*);
+
+extern void    abort(void);
+extern long    p9alarm(ulong);
+extern int     await(char*, int);
+extern int     awaitfor(int, char*, int);
+extern int     awaitnohang(char*, int);
+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     p9execl(char*, ...);
+extern int     p9rfork(int);
+extern int     noted(int);
+extern int     notify(void(*)(void*, char*));
+extern int     noteenable(char*);
+extern int     notedisable(char*);
+extern int     notifyon(char*);
+extern int     notifyoff(char*);
+extern int     p9open(char*, int);
+extern int     fd2path(int, char*, int);
+extern int     p9pipe(int*);
+extern long    readn(int, void*, long);
+extern int     remove(const char*);
+extern vlong   p9seek(int, vlong, int);
+extern int     p9sleep(long);
+extern Waitmsg*        p9wait(void);
+extern Waitmsg*        p9waitfor(int);
+extern Waitmsg*        waitnohang(void);
+extern int     p9waitpid(void);
+extern ulong   rendezvous(ulong, ulong);
+
+#ifndef NOPLAN9DEFINES
+#define alarm          p9alarm
+#define        dup             p9dup
+#define        exec            p9exec
+#define        execl   p9execl
+#define        seek            p9seek
+#define sleep          p9sleep
+#define wait           p9wait
+#define waitpid                p9waitpid
+#define rfork          p9rfork
+#define create         p9create
+#undef open
+#define open           p9open
+#define pipe           p9pipe
+#define        waitfor         p9waitfor
+#endif
+
+extern Dir*    dirstat(char*);
+extern Dir*    dirfstat(int);
+extern int     dirwstat(char*, Dir*);
+extern int     dirfwstat(int, Dir*);
+extern void    nulldir(Dir*);
+extern long    dirreadall(int, Dir**);
+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*);
+
+/* external names that we don't want to step on */
+#ifndef NOPLAN9DEFINES
+#define main   p9main
+#endif
+
+/* compiler directives on plan 9 */
+#define        SET(x)  ((x)=0)
+#define        USED(x) if(x){}else{}
+#ifdef __GNUC__
+#      if __GNUC__ >= 3
+#              undef USED
+#              define USED(x) ((void)(x))
+#      endif
+#endif
+
+/* command line */
+extern char    *argv0;
+extern void __fixargv0(void);
+#define        ARGBEGIN        for((argv0?0:(argv0=(__fixargv0(),*argv))),argv++,argc--;\
+                           argv[0] && argv[0][0]=='-' && argv[0][1];\
+                           argc--, argv++) {\
+                               char *_args, *_argt;\
+                               Rune _argc;\
+                               _args = &argv[0][1];\
+                               if(_args[0]=='-' && _args[1]==0){\
+                                       argc--; argv++; break;\
+                               }\
+                               _argc = 0;\
+                               while(*_args && (_args += chartorune(&_argc, _args)))\
+                               switch(_argc)
+#define        ARGEND          SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
+#define        ARGF()          (_argt=_args, _args="",\
+                               (*_argt? _argt: argv[1]? (argc--, *++argv): 0))
+#define        EARGF(x)        (_argt=_args, _args="",\
+                               (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
+
+#define        ARGC()          _argc
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* _LIB9_H_ */
diff --git a/include/u.h b/include/u.h
new file mode 100644 (file)
index 0000000..9b7bccb
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+Plan 9 from User Space include/u.h
+http://code.swtch.com/plan9port/src/tip/include/u.h
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef _U_H_
+#define _U_H_ 1
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define __BSD_VISIBLE 1 /* FreeBSD 5.x */
+#if defined(__sun__)
+#      define __EXTENSIONS__ 1 /* SunOS */
+#      if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__)
+               /* NOT USING #define __MAKECONTEXT_V2_SOURCE 1 / * SunOS */
+#      else
+#              define __MAKECONTEXT_V2_SOURCE 1
+#      endif
+#endif
+#define _BSD_SOURCE 1
+#define _NETBSD_SOURCE 1       /* NetBSD */
+#define _SVID_SOURCE 1
+#if !defined(__APPLE__) && !defined(__OpenBSD__)
+#      define _XOPEN_SOURCE 1000
+#      define _XOPEN_SOURCE_EXTENDED 1
+#endif
+#if defined(__FreeBSD__)
+#      include <sys/cdefs.h>
+       /* for strtoll */
+#      undef __ISO_C_VISIBLE
+#      define __ISO_C_VISIBLE 1999
+#      undef __LONG_LONG_SUPPORTED
+#      define __LONG_LONG_SUPPORTED
+#endif
+#define _LARGEFILE64_SOURCE 1
+#define _FILE_OFFSET_BITS 64
+
+#include <inttypes.h>
+
+#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 <math.h>
+#include <ctype.h>     /* for tolower */
+
+/*
+ * 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(__Linux26__)
+#              include <pthread.h>
+#              define PLAN9PORT_USING_PTHREADS 1
+#      endif
+#      if defined(__USE_MISC)
+#              undef _NEEDUSHORT
+#              undef _NEEDUINT
+#              undef _NEEDULONG
+#      endif
+#elif defined(__sun__)
+#      include <sys/types.h>
+#      include <pthread.h>
+#      define PLAN9PORT_USING_PTHREADS 1
+#      undef _NEEDUSHORT
+#      undef _NEEDUINT
+#      undef _NEEDULONG
+#      define nil 0    /* no cast to void* */
+#elif defined(__FreeBSD__)
+#      include <sys/types.h>
+#      include <osreldate.h>
+#      if __FreeBSD_version >= 500000
+#              define PLAN9PORT_USING_PTHREADS 1
+#              include <pthread.h>
+#      endif
+#      if !defined(_POSIX_SOURCE)
+#              undef _NEEDUSHORT
+#              undef _NEEDUINT
+#      endif
+#elif defined(__APPLE__)
+#      include <sys/types.h>
+#      include <pthread.h>
+#      define PLAN9PORT_USING_PTHREADS 1
+#      if __GNUC__ < 4
+#              undef _NEEDUSHORT
+#              undef _NEEDUINT
+#      endif
+#      undef _ANSI_SOURCE
+#      undef _POSIX_C_SOURCE
+#      undef _XOPEN_SOURCE
+#      if !defined(NSIG)
+#              define NSIG 32
+#      endif
+#      define _NEEDLL 1
+#elif defined(__NetBSD__)
+#      include <sched.h>
+#      include <sys/types.h>
+#      undef _NEEDUSHORT
+#      undef _NEEDUINT
+#      undef _NEEDULONG
+#elif defined(__OpenBSD__)
+#      include <sys/types.h>
+#      undef _NEEDUSHORT
+#      undef _NEEDUINT
+#      undef _NEEDULONG
+#else
+       /* No idea what system this is -- try some defaults */
+#      include <pthread.h>
+#      define PLAN9PORT_USING_PTHREADS 1
+#endif
+
+#ifndef O_DIRECT
+#define O_DIRECT 0
+#endif
+
+typedef signed char schar;
+
+#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 uint64_t u64int;
+typedef int64_t s64int;
+typedef uint8_t u8int;
+typedef int8_t s8int;
+typedef uint16_t u16int;
+typedef int16_t s16int;
+typedef uintptr_t uintptr;
+typedef intptr_t intptr;
+typedef uint32_t u32int;
+typedef int32_t s32int;
+
+#undef _NEEDUCHAR
+#undef _NEEDUSHORT
+#undef _NEEDUINT
+#undef _NEEDULONG
+
+/*
+ * Funny-named symbols to tip off 9l to autolink.
+ */
+#define AUTOLIB(x)     static int __p9l_autolib_ ## x = 1;
+#define AUTOFRAMEWORK(x) static int __p9l_autoframework_ ## x = 1;
+
+/*
+ * Gcc is too smart for its own good.
+ */
+#if defined(__GNUC__)
+#      undef strcmp    /* causes way too many warnings */
+#      if __GNUC__ >= 4 || (__GNUC__==3 && !defined(__APPLE_CC__))
+#              undef AUTOLIB
+#              define AUTOLIB(x) int __p9l_autolib_ ## x __attribute__ ((weak));
+#              undef AUTOFRAMEWORK
+#              define AUTOFRAMEWORK(x) int __p9l_autoframework_ ## x __attribute__ ((weak));
+#      else
+#              undef AUTOLIB
+#              define AUTOLIB(x) static int __p9l_autolib_ ## x __attribute__ ((unused));
+#              undef AUTOFRAMEWORK
+#              define AUTOFRAMEWORK(x) static int __p9l_autoframework_ ## x __attribute__ ((unused));
+#      endif
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/src/clean.bash b/src/clean.bash
new file mode 100755 (executable)
index 0000000..6f5da78
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+for i in lib9 libbio
+do
+       cd $i
+       make clean
+       cd ..
+done
+
+for i in cmd runtime
+do
+       cd $i
+       bash clean.bash
+       cd ..
+done
index b92e6204b67dfaa0be42ddc29741126e016e9038..4d987c124740a4744fc0a533d2e441ac831dde60 100644 (file)
@@ -3,7 +3,7 @@
 # license that can be found in the LICENSE file.
 
 YFLAGS=-d
-CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include
+CFLAGS=-I$(GOROOT)/include
 BIN=$(HOME)/bin
 O=o
 
@@ -26,7 +26,7 @@ YFILES=\
        a.y\
 
 $(TARG): $(OFILES)
-       cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) -lbio -l9
+       cc -o $(TARG) -L$(GOROOT)/lib $(OFILES) -lbio -l9
 
 $(OFILES): $(HFILES)
 
index d12b850c857cb42f6f88e643a53c81f22973b99b..df92cee014e941c99d4a48e8fbdd72ae8b552335 100644 (file)
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include
+CFLAGS=-I$(GOROOT)/include
 BIN=$(HOME)/bin
 O=o
 
@@ -32,7 +32,7 @@ LIB=\
        ../cc/cc.a$O
 
 $(TARG): $(OFILES) $(LIB)
-       cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) $(LIB) -lbio -l9
+       cc -o $(TARG) -L$(GOROOT)/lib $(OFILES) $(LIB) -lbio -l9
 
 $(OFILES): $(HFILES)
 
index cff0036481dd89aca2edc138b875d2518d5363f5..d119820e9e171c0323d40c2f47e058dbe354145d 100644 (file)
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include
+CFLAGS=-I$(GOROOT)/include
 BIN=$(HOME)/bin
 O=o
 
@@ -27,7 +27,7 @@ LIB=\
        ../gc/gc.a$O
 
 $(TARG): $(OFILES) $(LIB)
-       cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) $(LIB) -lbio -l9
+       cc -o $(TARG) -L$(GOROOT)/lib $(OFILES) $(LIB) -lbio -l9
 
 $(OFILES): $(HFILES)
 
index 7c15012a0ee2aa99e0b33dd8133ab65262abc19c..e87efafc93e65eae881a8e665fc54ce663b25a5c 100644 (file)
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include
+CFLAGS=-I$(GOROOT)/include
 BIN=$(HOME)/bin
 O=o
 
@@ -25,7 +25,7 @@ HFILES=\
 
 
 $(TARG): $(OFILES)
-       cc -o $(TARG) -L/home/r/plan9/lib $(OFILES) -lbio -l9
+       cc -o $(TARG) -L$(GOROOT)/lib $(OFILES) -lbio -l9
 
 $(OFILES): $(HFILES)
 
index 21cf17d09249e7ce96538146d6fdf3cb5a011b7c..e81c2afc02370040c47957ddd5b3eaba59302a71 100644 (file)
@@ -3,7 +3,7 @@
 # license that can be found in the LICENSE file.
 
 YFLAGS=-d
-CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include
+CFLAGS=-I$(GOROOT)/include
 BIN=$(HOME)/bin
 O=o
 
index 73860811e51002bd382c8d2c05f020f59267d53b..a67ab17b03bed6052a8fd8fb5361f822e18e2c80 100644 (file)
@@ -3,7 +3,7 @@
 # license that can be found in the LICENSE file.
 
 YFLAGS=-d
-CFLAGS=-I/home/r/plan9/include -I$(GOROOT)/include
+CFLAGS=-I$(GOROOT)/include
 BIN=$(HOME)/bin
 O=o
 
diff --git a/src/lib9/Makefile b/src/lib9/Makefile
new file mode 100644 (file)
index 0000000..12b72f0
--- /dev/null
@@ -0,0 +1,126 @@
+# Copyright 2009 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../Make.conf
+
+LIB=lib9.a
+
+NUM=\
+       charstod.$O\
+       pow10.$O\
+
+# Could add fmt/errfmt, but we want to pick it up from ./errstr.c instead.
+FMTOFILES=\
+       dofmt.$O\
+       fltfmt.$O\
+       fmt.$O\
+       fmtfd.$O\
+       fmtfdflush.$O\
+       fmtlocale.$O\
+       fmtlock2.$O\
+       fmtnull.$O\
+       fmtprint.$O\
+       fmtquote.$O\
+       fmtrune.$O\
+       fmtstr.$O\
+       fmtvprint.$O\
+       fprint.$O\
+       nan64.$O\
+       print.$O\
+       seprint.$O\
+       smprint.$O\
+       snprint.$O\
+       sprint.$O\
+       strtod.$O\
+       vfprint.$O\
+       vseprint.$O\
+       vsmprint.$O\
+       vsnprint.$O\
+       $(NUM)\
+
+UTFOFILES=\
+       rune.$O\
+       utfecpy.$O\
+       utflen.$O\
+       utfnlen.$O\
+       utfrrune.$O\
+       utfrune.$O\
+       utfutf.$O\
+       runetype.$O\
+
+LIB9OFILES=\
+       _p9dir.$O\
+       _exits.$O\
+       argv0.$O\
+       atoi.$O\
+       await.$O\
+       cleanname.$O\
+       create.$O\
+       dirfstat.$O\
+       dirfwstat.$O\
+       dirstat.$O\
+       dirwstat.$O\
+       dup.$O\
+       errstr.$O\
+       exec.$O\
+       execl.$O\
+       exitcode.$O\
+       exits.$O\
+       getenv.$O\
+       getfields.$O\
+       getuser.$O\
+       getwd.$O\
+       jmp.$O\
+       main.$O\
+       nan.$O\
+       notify.$O\
+       nulldir.$O\
+       open.$O\
+       pipe.$O\
+       readn.$O\
+       rfork.$O\
+       seek.$O\
+       strecpy.$O\
+       sysfatal.$O\
+       time.$O\
+       tokenize.$O\
+
+OFILES=\
+       $(LIB9OFILES)\
+       $(FMTOFILES)\
+       $(UTFOFILES)\
+
+HFILES=\
+       $(GOROOT)/include/u.h\
+       $(GOROOT)/include/libc.h\
+
+install: $(LIB)
+       cp $(LIB) $(GOROOT)/lib
+
+$(LIB): $(OFILES)
+       ar rsc $(LIB) $(OFILES)
+
+%.$O: fmt/%.c
+       $(CC) -c $(CFLAGS) -DPLAN9PORT -Ifmt $<
+
+%.$O: utf/%.c
+       $(CC) -c $(CFLAGS) $<
+
+clean:
+       rm -f *.$O *.6 6.out $(LIB)
+
+nuke: clean
+       rm -f $(GOROOT)/lib/$(LIB)
+
+#XLIB=$PLAN9/lib/$LIB
+
+#testfmt: testfmt.$O $XLIB
+#      $LD -o $target testfmt.$O
+
+#testfltfmt: testfltfmt.$O $XLIB
+#      $LD -o $target testfltfmt.$O
+
+#testprint: testprint.$O $XLIB
+#      $LD -o $target testprint.$O
+
diff --git a/src/lib9/_exits.c b/src/lib9/_exits.c
new file mode 100644 (file)
index 0000000..ea8ea74
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+Plan 9 from User Space src/lib9/_exits.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/_exits.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+void
+_exits(char *s)
+{
+       if(s == 0 || *s == 0)
+               _exit(0);
+       _exit(exitcode(s));
+}
diff --git a/src/lib9/_p9dir.c b/src/lib9/_p9dir.c
new file mode 100644 (file)
index 0000000..1c1aa65
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+Plan 9 from User Space src/lib9/_p9dir.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/_p9dir.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <grp.h>
+
+#if defined(__FreeBSD__)
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/ioctl.h>
+#endif
+
+#if defined(__OpenBSD__)
+#include <sys/disklabel.h>
+#include <sys/ioctl.h>
+#define _HAVEDISKLABEL
+static int diskdev[] = {
+       151,    /* aacd */
+       116,    /* ad */
+       157,    /* ar */
+       118,    /* afd */
+       133,    /* amrd */
+       13,     /* da */
+       102,    /* fla */
+       109,    /* idad */
+       95,     /* md */
+       131,    /* mlxd */
+       168,    /* pst */
+       147,    /* twed */
+       43,     /* vn */
+       3,      /* wd */
+       87,     /* wfd */
+       4,      /* da on FreeBSD 5 */
+};
+static int
+isdisk(struct stat *st)
+{
+       int i, dev;
+
+       if(!S_ISCHR(st->st_mode))
+               return 0;
+       dev = major(st->st_rdev);
+       for(i=0; i<nelem(diskdev); i++)
+               if(diskdev[i] == dev)
+                       return 1;
+       return 0;
+}
+#endif
+
+#if defined(__FreeBSD__)       /* maybe OpenBSD too? */
+char *diskdev[] = {
+       "aacd",
+       "ad",
+       "ar",
+       "afd",
+       "amrd",
+       "da",
+       "fla",
+       "idad",
+       "md",
+       "mlxd",
+       "pst",
+       "twed",
+       "vn",
+       "wd",
+       "wfd",
+       "da",
+};
+static int
+isdisk(struct stat *st)
+{
+       char *name;
+       int i, len;
+
+       if(!S_ISCHR(st->st_mode))
+               return 0;
+       name = devname(st->st_rdev, S_IFCHR);
+       for(i=0; i<nelem(diskdev); i++){
+               len = strlen(diskdev[i]);
+               if(strncmp(diskdev[i], name, len) == 0 && isdigit((uchar)name[len]))
+                       return 1;
+       }
+       return 0;
+}
+#endif
+
+
+#if defined(__linux__)
+#include <linux/hdreg.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#undef major
+#define major(dev) ((int)(((dev) >> 8) & 0xff))
+static vlong
+disksize(int fd, int dev)
+{
+       u64int u64;
+       long l;
+       struct hd_geometry geo;
+
+       memset(&geo, 0, sizeof geo);
+       l = 0;
+       u64 = 0;
+#ifdef BLKGETSIZE64
+       if(ioctl(fd, BLKGETSIZE64, &u64) >= 0)
+               return u64;
+#endif
+       if(ioctl(fd, BLKGETSIZE, &l) >= 0)
+               return l*512;
+       if(ioctl(fd, HDIO_GETGEO, &geo) >= 0)
+               return (vlong)geo.heads*geo.sectors*geo.cylinders*512;
+       return 0;
+}
+#define _HAVEDISKSIZE
+#endif
+
+#if !defined(__linux__) && !defined(__sun__)
+#define _HAVESTGEN
+#endif
+
+int _p9usepwlibrary = 1;
+/*
+ * Caching the last group and passwd looked up is
+ * a significant win (stupidly enough) on most systems.
+ * It's not safe for threaded programs, but neither is using
+ * getpwnam in the first place, so I'm not too worried.
+ */
+int
+_p9dir(struct stat *lst, struct stat *st, char *name, Dir *d, char **str, char *estr)
+{
+       char *s;
+       char tmp[20];
+       static struct group *g;
+       static struct passwd *p;
+       static int gid, uid;
+       int sz, fd;
+
+       fd = -1;
+       USED(fd);
+       sz = 0;
+       if(d)
+               memset(d, 0, sizeof *d);
+
+       /* name */
+       s = strrchr(name, '/');
+       if(s)
+               s++;
+       if(!s || !*s)
+               s = name;
+       if(*s == '/')
+               s++;
+       if(*s == 0)
+               s = "/";
+       if(d){
+               if(*str + strlen(s)+1 > estr)
+                       d->name = "oops";
+               else{
+                       strcpy(*str, s);
+                       d->name = *str;
+                       *str += strlen(*str)+1;
+               }
+       }
+       sz += strlen(s)+1;
+
+       /* user */
+       if(p && st->st_uid == uid && p->pw_uid == uid)
+               ;
+       else if(_p9usepwlibrary){
+               p = getpwuid(st->st_uid);
+               uid = st->st_uid;
+       }
+       if(p == nil || st->st_uid != uid || p->pw_uid != uid){
+               snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);
+               s = tmp;
+       }else
+               s = p->pw_name;
+       sz += strlen(s)+1;
+       if(d){
+               if(*str+strlen(s)+1 > estr)
+                       d->uid = "oops";
+               else{
+                       strcpy(*str, s);
+                       d->uid = *str;
+                       *str += strlen(*str)+1;
+               }
+       }
+
+       /* group */
+       if(g && st->st_gid == gid && g->gr_gid == gid)
+               ;
+       else if(_p9usepwlibrary){
+               g = getgrgid(st->st_gid);
+               gid = st->st_gid;
+       }
+       if(g == nil || st->st_gid != gid || g->gr_gid != gid){
+               snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);
+               s = tmp;
+       }else
+               s = g->gr_name;
+       sz += strlen(s)+1;
+       if(d){
+               if(*str + strlen(s)+1 > estr)
+                       d->gid = "oops";
+               else{
+                       strcpy(*str, s);
+                       d->gid = *str;
+                       *str += strlen(*str)+1;
+               }
+       }
+
+       if(d){
+               d->type = 'M';
+
+               d->muid = "";
+               d->qid.path = ((uvlong)st->st_dev<<32) | st->st_ino;
+#ifdef _HAVESTGEN
+               d->qid.vers = st->st_gen;
+#endif
+               if(d->qid.vers == 0)
+                       d->qid.vers = st->st_mtime + st->st_ctime;
+               d->mode = st->st_mode&0777;
+               d->atime = st->st_atime;
+               d->mtime = st->st_mtime;
+               d->length = st->st_size;
+
+               if(S_ISDIR(st->st_mode)){
+                       d->length = 0;
+                       d->mode |= DMDIR;
+                       d->qid.type = QTDIR;
+               }
+               if(S_ISLNK(lst->st_mode))       /* yes, lst not st */
+                       d->mode |= DMSYMLINK;
+               if(S_ISFIFO(st->st_mode))
+                       d->mode |= DMNAMEDPIPE;
+               if(S_ISSOCK(st->st_mode))
+                       d->mode |= DMSOCKET;
+               if(S_ISBLK(st->st_mode)){
+                       d->mode |= DMDEVICE;
+                       d->qid.path = ('b'<<16)|st->st_rdev;
+               }
+               if(S_ISCHR(st->st_mode)){
+                       d->mode |= DMDEVICE;
+                       d->qid.path = ('c'<<16)|st->st_rdev;
+               }
+               /* fetch real size for disks */
+#ifdef _HAVEDISKSIZE
+               if(S_ISBLK(st->st_mode) && (fd = open(name, O_RDONLY)) >= 0){
+                       d->length = disksize(fd, major(st->st_dev));
+                       close(fd);
+               }
+#endif
+#if defined(DIOCGMEDIASIZE)
+               if(isdisk(st)){
+                       int fd;
+                       off_t mediasize;
+
+                       if((fd = open(name, O_RDONLY)) >= 0){
+                               if(ioctl(fd, DIOCGMEDIASIZE, &mediasize) >= 0)
+                                       d->length = mediasize;
+                               close(fd);
+                       }
+               }
+#elif defined(_HAVEDISKLABEL)
+               if(isdisk(st)){
+                       int fd, n;
+                       struct disklabel lab;
+
+                       if((fd = open(name, O_RDONLY)) < 0)
+                               goto nosize;
+                       if(ioctl(fd, DIOCGDINFO, &lab) < 0)
+                               goto nosize;
+                       n = minor(st->st_rdev)&7;
+                       if(n >= lab.d_npartitions)
+                               goto nosize;
+
+                       d->length = (vlong)(lab.d_partitions[n].p_size) * lab.d_secsize;
+
+               nosize:
+                       if(fd >= 0)
+                               close(fd);
+               }
+#endif
+       }
+
+       return sz;
+}
+
diff --git a/src/lib9/argv0.c b/src/lib9/argv0.c
new file mode 100644 (file)
index 0000000..f109efd
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Plan 9 from User Space src/lib9/argv0.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/argv0.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <lib9.h>
+
+char *argv0;
+
+/*
+ * Mac OS can't deal with files that only declare data.
+ * ARGBEGIN mentions this function so that this file gets pulled in.
+ */
+void __fixargv0(void) { }
diff --git a/src/lib9/atoi.c b/src/lib9/atoi.c
new file mode 100644 (file)
index 0000000..37a1782
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+Plan 9 from User Space src/lib9/ato*.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/atoi.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+int
+atoi(char *s)
+{
+       return strtol(s, 0, 0);
+}
+
+long
+atol(char *s)
+{
+       return strtol(s, 0, 0);
+}
+
+vlong
+atoll(char *s)
+{
+       return strtoll(s, 0, 0);
+}
diff --git a/src/lib9/await.c b/src/lib9/await.c
new file mode 100644 (file)
index 0000000..90be598
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+Plan 9 from User Space src/lib9/await.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/await.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+Portions Copyright 2009 The Go Authors.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#define NOPLAN9DEFINES
+#include <u.h>
+#include <libc.h>
+
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#ifndef WCOREDUMP      /* not on Mac OS X Tiger */
+#define WCOREDUMP(status) 0
+#endif
+
+static struct {
+       int sig;
+       char *str;
+} tab[] = {
+       SIGHUP,         "hangup",
+       SIGINT,         "interrupt",
+       SIGQUIT,                "quit",
+       SIGILL,         "sys: illegal instruction",
+       SIGTRAP,                "sys: breakpoint",
+       SIGABRT,                "sys: abort",
+#ifdef SIGEMT
+       SIGEMT,         "sys: emulate instruction executed",
+#endif
+       SIGFPE,         "sys: fp: trap",
+       SIGKILL,                "sys: kill",
+       SIGBUS,         "sys: bus error",
+       SIGSEGV,                "sys: segmentation violation",
+       SIGALRM,                "alarm",
+       SIGTERM,                "kill",
+       SIGURG,         "sys: urgent condition on socket",
+       SIGSTOP,                "sys: stop",
+       SIGTSTP,                "sys: tstp",
+       SIGCONT,                "sys: cont",
+       SIGCHLD,                "sys: child",
+       SIGTTIN,                "sys: ttin",
+       SIGTTOU,                "sys: ttou",
+#ifdef SIGIO   /* not on Mac OS X Tiger */
+       SIGIO,          "sys: i/o possible on fd",
+#endif
+       SIGXCPU,                "sys: cpu time limit exceeded",
+       SIGXFSZ,                "sys: file size limit exceeded",
+       SIGVTALRM,      "sys: virtual time alarm",
+       SIGPROF,                "sys: profiling timer alarm",
+#ifdef SIGWINCH        /* not on Mac OS X Tiger */
+       SIGWINCH,       "sys: window size change",
+#endif
+#ifdef SIGINFO
+       SIGINFO,                "sys: status request",
+#endif
+       SIGUSR1,                "sys: usr1",
+       SIGUSR2,                "sys: usr2",
+       SIGPIPE,                "sys: write on closed pipe",
+};
+
+char*
+_p9sigstr(int sig, char *tmp)
+{
+       int i;
+
+       for(i=0; i<nelem(tab); i++)
+               if(tab[i].sig == sig)
+                       return tab[i].str;
+       if(tmp == nil)
+               return nil;
+       sprint(tmp, "sys: signal %d", sig);
+       return tmp;
+}
+
+int
+_p9strsig(char *s)
+{
+       int i;
+
+       for(i=0; i<nelem(tab); i++)
+               if(strcmp(s, tab[i].str) == 0)
+                       return tab[i].sig;
+       return 0;
+}
+
+static Waitmsg*
+_wait(int pid4, int opt)
+{
+       int pid, status, cd;
+       struct rusage ru;
+       char tmp[64];
+       ulong u, s;
+       Waitmsg *w;
+
+       w = malloc(sizeof *w + 200);
+       if(w == nil)
+               return nil;
+       memset(w, 0, sizeof *w);
+       w->msg = (char*)&w[1];
+
+       for(;;){
+               /* On Linux, pid==-1 means anyone; on SunOS, it's pid==0. */
+               if(pid4 == -1)
+                       pid = wait3(&status, opt, &ru);
+               else
+                       pid = wait4(pid4, &status, opt, &ru);
+               if(pid <= 0) {
+                       free(w);
+                       return nil;
+               }
+               u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
+               s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
+               w->pid = pid;
+               w->time[0] = u;
+               w->time[1] = s;
+               w->time[2] = u+s;
+               if(WIFEXITED(status)){
+                       if(status)
+                               sprint(w->msg, "%d", status);
+                       return w;
+               }
+               if(WIFSIGNALED(status)){
+                       cd = WCOREDUMP(status);
+                       sprint(w->msg, "signal: %s", _p9sigstr(WTERMSIG(status), tmp));
+                       if(cd)
+                               strcat(w->msg, " (core dumped)");
+                       return w;
+               }
+       }
+}
+
+Waitmsg*
+p9wait(void)
+{
+       return _wait(-1, 0);
+}
+
+Waitmsg*
+p9waitfor(int pid)
+{
+       return _wait(pid, 0);
+}
+
+Waitmsg*
+p9waitnohang(void)
+{
+       return _wait(-1, WNOHANG);
+}
+
+int
+p9waitpid(void)
+{
+       int status;
+       return wait(&status);
+}
diff --git a/src/lib9/cleanname.c b/src/lib9/cleanname.c
new file mode 100644 (file)
index 0000000..fee4038
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+Inferno libkern/cleanname.c
+http://code.google.com/p/inferno-os/source/browse/libkern/cleanname.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+/*
+ * In place, rewrite name to compress multiple /, eliminate ., and process ..
+ */
+#define SEP(x) ((x)=='/' || (x) == 0)
+char*
+cleanname(char *name)
+{
+       char *p, *q, *dotdot;
+       int rooted;
+
+       rooted = name[0] == '/';
+
+       /*
+        * invariants:
+        *      p points at beginning of path element we're considering.
+        *      q points just past the last path element we wrote (no slash).
+        *      dotdot points just past the point where .. cannot backtrack
+        *              any further (no slash).
+        */
+       p = q = dotdot = name+rooted;
+       while(*p) {
+               if(p[0] == '/') /* null element */
+                       p++;
+               else if(p[0] == '.' && SEP(p[1]))
+                       p += 1; /* don't count the separator in case it is nul */
+               else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) {
+                       p += 2;
+                       if(q > dotdot) {        /* can backtrack */
+                               while(--q > dotdot && *q != '/')
+                                       ;
+                       } else if(!rooted) {    /* /.. is / but ./../ is .. */
+                               if(q != name)
+                                       *q++ = '/';
+                               *q++ = '.';
+                               *q++ = '.';
+                               dotdot = q;
+                       }
+               } else {        /* real path element */
+                       if(q != name+rooted)
+                               *q++ = '/';
+                       while((*q = *p) != '/' && *q != 0)
+                               p++, q++;
+               }
+       }
+       if(q == name)   /* empty string is really ``.'' */
+               *q++ = '.';
+       *q = '\0';
+       return name;
+}
diff --git a/src/lib9/create.c b/src/lib9/create.c
new file mode 100644 (file)
index 0000000..8e5cbc3
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+Plan 9 from User Space src/lib9/create.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/create.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#define _GNU_SOURCE    /* for Linux O_DIRECT */
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <sys/file.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libc.h>
+#include <sys/stat.h>
+#ifndef O_DIRECT
+#define O_DIRECT 0
+#endif
+
+int
+p9create(char *path, int mode, ulong perm)
+{
+       int fd, cexec, umode, rclose, lock, rdwr;
+       struct flock fl;
+
+       rdwr = mode&3;
+       lock = mode&OLOCK;
+       cexec = mode&OCEXEC;
+       rclose = mode&ORCLOSE;
+       mode &= ~(ORCLOSE|OCEXEC|OLOCK);
+
+       /* XXX should get mode mask right? */
+       fd = -1;
+       if(perm&DMDIR){
+               if(mode != OREAD){
+                       werrstr("bad mode in directory create");
+                       goto out;
+               }
+               if(mkdir(path, perm&0777) < 0)
+                       goto out;
+               fd = open(path, O_RDONLY);
+       }else{
+               umode = (mode&3)|O_CREAT|O_TRUNC;
+               mode &= ~(3|OTRUNC);
+               if(mode&ODIRECT){
+                       umode |= O_DIRECT;
+                       mode &= ~ODIRECT;
+               }
+               if(mode&OEXCL){
+                       umode |= O_EXCL;
+                       mode &= ~OEXCL;
+               }
+               if(mode&OAPPEND){
+                       umode |= O_APPEND;
+                       mode &= ~OAPPEND;
+               }
+               if(mode){
+                       werrstr("unsupported mode in create");
+                       goto out;
+               }
+               fd = open(path, umode, perm);
+       }
+out:
+       if(fd >= 0){
+               if(lock){
+                       fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;
+                       fl.l_whence = SEEK_SET;
+                       fl.l_start = 0;
+                       fl.l_len = 0;
+                       if(fcntl(fd, F_SETLK, &fl) < 0){
+                               close(fd);
+                               werrstr("lock: %r");
+                               return -1;
+                       }
+               }
+               if(cexec)
+                       fcntl(fd, F_SETFL, FD_CLOEXEC);
+               if(rclose)
+                       remove(path);
+       }
+       return fd;
+}
diff --git a/src/lib9/dirfstat.c b/src/lib9/dirfstat.c
new file mode 100644 (file)
index 0000000..17fe10a
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+Plan 9 from User Space src/lib9/dirfstat.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/dirfstat.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+#include <sys/stat.h>
+
+extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*);
+
+Dir*
+dirfstat(int fd)
+{
+       struct stat st;
+       int nstr;
+       Dir *d;
+       char *str, tmp[100];
+
+       if(fstat(fd, &st) < 0)
+               return nil;
+
+       snprint(tmp, sizeof tmp, "/dev/fd/%d", fd);
+       nstr = _p9dir(&st, &st, tmp, nil, nil, nil);
+       d = malloc(sizeof(Dir)+nstr);
+       if(d == nil)
+               return nil;
+       memset(d, 0, sizeof(Dir)+nstr);
+       str = (char*)&d[1];
+       _p9dir(&st, &st, tmp, d, &str, str+nstr);
+       return d;
+}
+
diff --git a/src/lib9/dirfwstat.c b/src/lib9/dirfwstat.c
new file mode 100644 (file)
index 0000000..657a98d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+Plan 9 from User Space src/lib9/dirfwstat.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/dirfwstat.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#define NOPLAN9DEFINES
+#include <u.h>
+#include <libc.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__linux__)
+/* do nothing -- futimes exists and is fine */
+
+#elif defined(__SunOS5_9__)
+/* use futimesat */
+static int
+futimes(int fd, struct timeval *tv)
+{
+       return futimesat(fd, 0, tv);
+}
+
+#else
+/* provide dummy */
+/* rename just in case -- linux provides an unusable one */
+#undef futimes
+#define futimes myfutimes
+static int
+futimes(int fd, struct timeval *tv)
+{
+       werrstr("futimes not available");
+       return -1;
+}
+
+#endif
+
+int
+dirfwstat(int fd, Dir *dir)
+{
+       int ret;
+       struct timeval tv[2];
+
+       ret = 0;
+       if(~dir->mode != 0){
+               if(fchmod(fd, dir->mode) < 0)
+                       ret = -1;
+       }
+       if(~dir->mtime != 0){
+               tv[0].tv_sec = dir->mtime;
+               tv[0].tv_usec = 0;
+               tv[1].tv_sec = dir->mtime;
+               tv[1].tv_usec = 0;
+               if(futimes(fd, tv) < 0)
+                       ret = -1;
+       }
+       return ret;
+}
+
diff --git a/src/lib9/dirstat.c b/src/lib9/dirstat.c
new file mode 100644 (file)
index 0000000..5cb6790
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+Plan 9 from User Space src/lib9/dirstat.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/dirstat.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+#include <sys/stat.h>
+
+extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*);
+
+Dir*
+dirstat(char *file)
+{
+       struct stat lst;
+       struct stat st;
+       int nstr;
+       Dir *d;
+       char *str;
+
+       if(lstat(file, &lst) < 0)
+               return nil;
+       st = lst;
+       if((lst.st_mode&S_IFMT) == S_IFLNK)
+               stat(file, &st);
+
+       nstr = _p9dir(&lst, &st, file, nil, nil, nil);
+       d = malloc(sizeof(Dir)+nstr);
+       if(d == nil)
+               return nil;
+       memset(d, 0, sizeof(Dir)+nstr);
+       str = (char*)&d[1];
+       _p9dir(&lst, &st, file, d, &str, str+nstr);
+       return d;
+}
+
diff --git a/src/lib9/dirwstat.c b/src/lib9/dirwstat.c
new file mode 100644 (file)
index 0000000..2646cba
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Plan 9 from User Space src/lib9/dirwstat.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/dirwstat.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+#include <sys/time.h>
+#include <utime.h>
+
+int
+dirwstat(char *file, Dir *dir)
+{
+       struct utimbuf ub;
+
+       /* BUG handle more */
+       if(~dir->mtime == 0)
+               return 0;
+
+       ub.actime = dir->mtime;
+       ub.modtime = dir->mtime;
+       return utime(file, &ub);
+}
diff --git a/src/lib9/dup.c b/src/lib9/dup.c
new file mode 100644 (file)
index 0000000..9fdfdb8
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+Plan 9 from User Space src/lib9/dup.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/dup.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#include <libc.h>
+
+#undef dup
+
+int
+p9dup(int old, int new)
+{
+       if(new == -1)
+               return dup(old);
+       return dup2(old, new);
+}
diff --git a/src/lib9/errstr.c b/src/lib9/errstr.c
new file mode 100644 (file)
index 0000000..f42f2b5
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+Plan 9 from User Space src/lib9/errstr.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/errstr.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/*
+ * We assume there's only one error buffer for the whole system.
+ * If you use ffork, you need to provide a _syserrstr.  Since most
+ * people will use libthread (which provides a _syserrstr), this is
+ * okay.
+ */
+
+#include <u.h>
+#include <errno.h>
+#include <string.h>
+#include <libc.h>
+
+enum
+{
+       EPLAN9 = 0x19283745
+};
+
+char *(*_syserrstr)(void);
+static char xsyserr[ERRMAX];
+static char*
+getsyserr(void)
+{
+       char *s;
+
+       s = nil;
+       if(_syserrstr)
+               s = (*_syserrstr)();
+       if(s == nil)
+               s = xsyserr;
+       return s;
+}
+
+int
+errstr(char *err, uint n)
+{
+       char tmp[ERRMAX];
+       char *syserr;
+
+       strecpy(tmp, tmp+ERRMAX, err);
+       rerrstr(err, n);
+       syserr = getsyserr();
+       strecpy(syserr, syserr+ERRMAX, tmp);
+       errno = EPLAN9;
+       return 0;
+}
+
+void
+rerrstr(char *err, uint n)
+{
+       char *syserr;
+
+       syserr = getsyserr();
+       if(errno == EINTR)
+               strcpy(syserr, "interrupted");
+       else if(errno != EPLAN9)
+               strcpy(syserr, strerror(errno));
+       strecpy(err, err+n, syserr);
+}
+
+/* replaces __errfmt in libfmt */
+
+int
+__errfmt(Fmt *f)
+{
+       if(errno == EPLAN9)
+               return fmtstrcpy(f, getsyserr());
+       return fmtstrcpy(f, strerror(errno));
+}
+
+void
+werrstr(char *fmt, ...)
+{
+       va_list arg;
+       char buf[ERRMAX];
+
+       va_start(arg, fmt);
+       vseprint(buf, buf+ERRMAX, fmt, arg);
+       va_end(arg);
+       errstr(buf, ERRMAX);
+}
+
diff --git a/src/lib9/exec.c b/src/lib9/exec.c
new file mode 100644 (file)
index 0000000..f2ad0f9
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Plan 9 from User Space src/lib9/exec.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/exec.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#include <libc.h>
+
+int
+exec(char *prog, char *argv[])
+{
+       /* to mimic plan 9 should be just exec, but execvp is a better fit for unix */
+       return execvp(prog, argv);
+}
diff --git a/src/lib9/execl.c b/src/lib9/execl.c
new file mode 100644 (file)
index 0000000..9e42ad3
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+Plan 9 from User Space src/lib9/execl.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/execl.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#include <libc.h>
+
+int
+execl(char *prog, ...)
+{
+       int i;
+       va_list arg;
+       char **argv;
+
+       va_start(arg, prog);
+       for(i=0; va_arg(arg, char*) != nil; i++)
+               ;
+       va_end(arg);
+
+       argv = malloc((i+1)*sizeof(char*));
+       if(argv == nil)
+               return -1;
+
+       va_start(arg, prog);
+       for(i=0; (argv[i] = va_arg(arg, char*)) != nil; i++)
+               ;
+       va_end(arg);
+
+       exec(prog, argv);
+       free(argv);
+       return -1;
+}
+
diff --git a/src/lib9/exitcode.c b/src/lib9/exitcode.c
new file mode 100644 (file)
index 0000000..234492a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Plan 9 from User Space src/lib9/exitcode.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/exitcode.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+int
+exitcode(char *s)
+{
+       return 1;
+}
+
diff --git a/src/lib9/fmt/charstod.c b/src/lib9/fmt/charstod.c
new file mode 100644 (file)
index 0000000..b8096e8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * Reads a floating-point number by interpreting successive characters
+ * returned by (*f)(vp).  The last call it makes to f terminates the
+ * scan, so is not a character in the number.  It may therefore be
+ * necessary to back up the input stream up one byte after calling charstod.
+ */
+
+double
+fmtcharstod(int(*f)(void*), void *vp)
+{
+       double num, dem;
+       int neg, eneg, dig, exp, c;
+
+       num = 0;
+       neg = 0;
+       dig = 0;
+       exp = 0;
+       eneg = 0;
+
+       c = (*f)(vp);
+       while(c == ' ' || c == '\t')
+               c = (*f)(vp);
+       if(c == '-' || c == '+'){
+               if(c == '-')
+                       neg = 1;
+               c = (*f)(vp);
+       }
+       while(c >= '0' && c <= '9'){
+               num = num*10 + c-'0';
+               c = (*f)(vp);
+       }
+       if(c == '.')
+               c = (*f)(vp);
+       while(c >= '0' && c <= '9'){
+               num = num*10 + c-'0';
+               dig++;
+               c = (*f)(vp);
+       }
+       if(c == 'e' || c == 'E'){
+               c = (*f)(vp);
+               if(c == '-' || c == '+'){
+                       if(c == '-'){
+                               dig = -dig;
+                               eneg = 1;
+                       }
+                       c = (*f)(vp);
+               }
+               while(c >= '0' && c <= '9'){
+                       exp = exp*10 + c-'0';
+                       c = (*f)(vp);
+               }
+       }
+       exp -= dig;
+       if(exp < 0){
+               exp = -exp;
+               eneg = !eneg;
+       }
+       dem = __fmtpow10(exp);
+       if(eneg)
+               num /= dem;
+       else
+               num *= dem;
+       if(neg)
+               return -num;
+       return num;
+}
diff --git a/src/lib9/fmt/dofmt.c b/src/lib9/fmt/dofmt.c
new file mode 100644 (file)
index 0000000..ea43940
--- /dev/null
@@ -0,0 +1,629 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/* format the output into f->to and return the number of characters fmted  */
+int
+dofmt(Fmt *f, char *fmt)
+{
+       Rune rune, *rt, *rs;
+       int r;
+       char *t, *s;
+       int n, nfmt;
+
+       nfmt = f->nfmt;
+       for(;;){
+               if(f->runes){
+                       rt = (Rune*)f->to;
+                       rs = (Rune*)f->stop;
+                       while((r = *(uchar*)fmt) && r != '%'){
+                               if(r < Runeself)
+                                       fmt++;
+                               else{
+                                       fmt += chartorune(&rune, fmt);
+                                       r = rune;
+                               }
+                               FMTRCHAR(f, rt, rs, r);
+                       }
+                       fmt++;
+                       f->nfmt += rt - (Rune *)f->to;
+                       f->to = rt;
+                       if(!r)
+                               return f->nfmt - nfmt;
+                       f->stop = rs;
+               }else{
+                       t = (char*)f->to;
+                       s = (char*)f->stop;
+                       while((r = *(uchar*)fmt) && r != '%'){
+                               if(r < Runeself){
+                                       FMTCHAR(f, t, s, r);
+                                       fmt++;
+                               }else{
+                                       n = chartorune(&rune, fmt);
+                                       if(t + n > s){
+                                               t = (char*)__fmtflush(f, t, n);
+                                               if(t != nil)
+                                                       s = (char*)f->stop;
+                                               else
+                                                       return -1;
+                                       }
+                                       while(n--)
+                                               *t++ = *fmt++;
+                               }
+                       }
+                       fmt++;
+                       f->nfmt += t - (char *)f->to;
+                       f->to = t;
+                       if(!r)
+                               return f->nfmt - nfmt;
+                       f->stop = s;
+               }
+
+               fmt = (char*)__fmtdispatch(f, fmt, 0);
+               if(fmt == nil)
+                       return -1;
+       }
+}
+
+void *
+__fmtflush(Fmt *f, void *t, int len)
+{
+       if(f->runes)
+               f->nfmt += (Rune*)t - (Rune*)f->to;
+       else
+               f->nfmt += (char*)t - (char *)f->to;
+       f->to = t;
+       if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
+               f->stop = f->to;
+               return nil;
+       }
+       return f->to;
+}
+
+/*
+ * put a formatted block of memory sz bytes long of n runes into the output buffer,
+ * left/right justified in a field of at least f->width characters (if FmtWidth is set)
+ */
+int
+__fmtpad(Fmt *f, int n)
+{
+       char *t, *s;
+       int i;
+
+       t = (char*)f->to;
+       s = (char*)f->stop;
+       for(i = 0; i < n; i++)
+               FMTCHAR(f, t, s, ' ');
+       f->nfmt += t - (char *)f->to;
+       f->to = t;
+       return 0;
+}
+
+int
+__rfmtpad(Fmt *f, int n)
+{
+       Rune *t, *s;
+       int i;
+
+       t = (Rune*)f->to;
+       s = (Rune*)f->stop;
+       for(i = 0; i < n; i++)
+               FMTRCHAR(f, t, s, ' ');
+       f->nfmt += t - (Rune *)f->to;
+       f->to = t;
+       return 0;
+}
+
+int
+__fmtcpy(Fmt *f, const void *vm, int n, int sz)
+{
+       Rune *rt, *rs, r;
+       char *t, *s, *m, *me;
+       ulong fl;
+       int nc, w;
+
+       m = (char*)vm;
+       me = m + sz;
+       fl = f->flags;
+       w = 0;
+       if(fl & FmtWidth)
+               w = f->width;
+       if((fl & FmtPrec) && n > f->prec)
+               n = f->prec;
+       if(f->runes){
+               if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
+                       return -1;
+               rt = (Rune*)f->to;
+               rs = (Rune*)f->stop;
+               for(nc = n; nc > 0; nc--){
+                       r = *(uchar*)m;
+                       if(r < Runeself)
+                               m++;
+                       else if((me - m) >= UTFmax || fullrune(m, me-m))
+                               m += chartorune(&r, m);
+                       else
+                               break;
+                       FMTRCHAR(f, rt, rs, r);
+               }
+               f->nfmt += rt - (Rune *)f->to;
+               f->to = rt;
+               if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
+                       return -1;
+       }else{
+               if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
+                       return -1;
+               t = (char*)f->to;
+               s = (char*)f->stop;
+               for(nc = n; nc > 0; nc--){
+                       r = *(uchar*)m;
+                       if(r < Runeself)
+                               m++;
+                       else if((me - m) >= UTFmax || fullrune(m, me-m))
+                               m += chartorune(&r, m);
+                       else
+                               break;
+                       FMTRUNE(f, t, s, r);
+               }
+               f->nfmt += t - (char *)f->to;
+               f->to = t;
+               if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
+                       return -1;
+       }
+       return 0;
+}
+
+int
+__fmtrcpy(Fmt *f, const void *vm, int n)
+{
+       Rune r, *m, *me, *rt, *rs;
+       char *t, *s;
+       ulong fl;
+       int w;
+
+       m = (Rune*)vm;
+       fl = f->flags;
+       w = 0;
+       if(fl & FmtWidth)
+               w = f->width;
+       if((fl & FmtPrec) && n > f->prec)
+               n = f->prec;
+       if(f->runes){
+               if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
+                       return -1;
+               rt = (Rune*)f->to;
+               rs = (Rune*)f->stop;
+               for(me = m + n; m < me; m++)
+                       FMTRCHAR(f, rt, rs, *m);
+               f->nfmt += rt - (Rune *)f->to;
+               f->to = rt;
+               if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
+                       return -1;
+       }else{
+               if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
+                       return -1;
+               t = (char*)f->to;
+               s = (char*)f->stop;
+               for(me = m + n; m < me; m++){
+                       r = *m;
+                       FMTRUNE(f, t, s, r);
+               }
+               f->nfmt += t - (char *)f->to;
+               f->to = t;
+               if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
+                       return -1;
+       }
+       return 0;
+}
+
+/* fmt out one character */
+int
+__charfmt(Fmt *f)
+{
+       char x[1];
+
+       x[0] = va_arg(f->args, int);
+       f->prec = 1;
+       return __fmtcpy(f, (const char*)x, 1, 1);
+}
+
+/* fmt out one rune */
+int
+__runefmt(Fmt *f)
+{
+       Rune x[1];
+
+       x[0] = va_arg(f->args, int);
+       return __fmtrcpy(f, (const void*)x, 1);
+}
+
+/* public helper routine: fmt out a null terminated string already in hand */
+int
+fmtstrcpy(Fmt *f, char *s)
+{
+       int i, j;
+
+       if(!s)
+               return __fmtcpy(f, "<nil>", 5, 5);
+       /* if precision is specified, make sure we don't wander off the end */
+       if(f->flags & FmtPrec){
+#ifdef PLAN9PORT
+               Rune r;
+               i = 0;
+               for(j=0; j<f->prec && s[i]; j++)
+                       i += chartorune(&r, s+i);
+#else
+               /* ANSI requires precision in bytes, not Runes */
+               for(i=0; i<f->prec; i++)
+                       if(s[i] == 0)
+                               break;
+               j = utfnlen(s, i);      /* won't print partial at end */
+#endif
+               return __fmtcpy(f, s, j, i);
+       }
+       return __fmtcpy(f, s, utflen(s), strlen(s));
+}
+
+/* fmt out a null terminated utf string */
+int
+__strfmt(Fmt *f)
+{
+       char *s;
+
+       s = va_arg(f->args, char *);
+       return fmtstrcpy(f, s);
+}
+
+/* public helper routine: fmt out a null terminated rune string already in hand */
+int
+fmtrunestrcpy(Fmt *f, Rune *s)
+{
+       Rune *e;
+       int n, p;
+
+       if(!s)
+               return __fmtcpy(f, "<nil>", 5, 5);
+       /* if precision is specified, make sure we don't wander off the end */
+       if(f->flags & FmtPrec){
+               p = f->prec;
+               for(n = 0; n < p; n++)
+                       if(s[n] == 0)
+                               break;
+       }else{
+               for(e = s; *e; e++)
+                       ;
+               n = e - s;
+       }
+       return __fmtrcpy(f, s, n);
+}
+
+/* fmt out a null terminated rune string */
+int
+__runesfmt(Fmt *f)
+{
+       Rune *s;
+
+       s = va_arg(f->args, Rune *);
+       return fmtrunestrcpy(f, s);
+}
+
+/* fmt a % */
+int
+__percentfmt(Fmt *f)
+{
+       Rune x[1];
+
+       x[0] = f->r;
+       f->prec = 1;
+       return __fmtrcpy(f, (const void*)x, 1);
+}
+
+/* fmt an integer */
+int
+__ifmt(Fmt *f)
+{
+       char buf[140], *p, *conv;
+       /* 140: for 64 bits of binary + 3-byte sep every 4 digits */
+       uvlong vu;
+       ulong u;
+       int neg, base, i, n, fl, w, isv;
+       int ndig, len, excess, bytelen;
+       char *grouping;
+       char *thousands;
+
+       neg = 0;
+       fl = f->flags;
+       isv = 0;
+       vu = 0;
+       u = 0;
+#ifndef PLAN9PORT
+       /*
+        * Unsigned verbs for ANSI C
+        */
+       switch(f->r){
+       case 'o':
+       case 'p':
+       case 'u':
+       case 'x':
+       case 'X':
+               fl |= FmtUnsigned;
+               fl &= ~(FmtSign|FmtSpace);
+               break;
+       }
+#endif
+       if(f->r == 'p'){
+               u = (ulong)va_arg(f->args, void*);
+               f->r = 'x';
+               fl |= FmtUnsigned;
+       }else if(fl & FmtVLong){
+               isv = 1;
+               if(fl & FmtUnsigned)
+                       vu = va_arg(f->args, uvlong);
+               else
+                       vu = va_arg(f->args, vlong);
+       }else if(fl & FmtLong){
+               if(fl & FmtUnsigned)
+                       u = va_arg(f->args, ulong);
+               else
+                       u = va_arg(f->args, long);
+       }else if(fl & FmtByte){
+               if(fl & FmtUnsigned)
+                       u = (uchar)va_arg(f->args, int);
+               else
+                       u = (char)va_arg(f->args, int);
+       }else if(fl & FmtShort){
+               if(fl & FmtUnsigned)
+                       u = (ushort)va_arg(f->args, int);
+               else
+                       u = (short)va_arg(f->args, int);
+       }else{
+               if(fl & FmtUnsigned)
+                       u = va_arg(f->args, uint);
+               else
+                       u = va_arg(f->args, int);
+       }
+       conv = "0123456789abcdef";
+       grouping = "\4";        /* for hex, octal etc. (undefined by spec but nice) */
+       thousands = f->thousands;
+       switch(f->r){
+       case 'd':
+       case 'i':
+       case 'u':
+               base = 10;
+               grouping = f->grouping;
+               break;
+       case 'X':
+               conv = "0123456789ABCDEF";
+               /* fall through */
+       case 'x':
+               base = 16;
+               thousands = ":";
+               break;
+       case 'b':
+               base = 2;
+               thousands = ":";
+               break;
+       case 'o':
+               base = 8;
+               break;
+       default:
+               return -1;
+       }
+       if(!(fl & FmtUnsigned)){
+               if(isv && (vlong)vu < 0){
+                       vu = -(vlong)vu;
+                       neg = 1;
+               }else if(!isv && (long)u < 0){
+                       u = -(long)u;
+                       neg = 1;
+               }
+       }
+       p = buf + sizeof buf - 1;
+       n = 0;  /* in runes */
+       excess = 0;     /* number of bytes > number runes */
+       ndig = 0;
+       len = utflen(thousands);
+       bytelen = strlen(thousands);
+       if(isv){
+               while(vu){
+                       i = vu % base;
+                       vu /= base;
+                       if((fl & FmtComma) && n % 4 == 3){
+                               *p-- = ',';
+                               n++;
+                       }
+                       if((fl & FmtApost) && __needsep(&ndig, &grouping)){
+                               n += len;
+                               excess += bytelen - len;
+                               p -= bytelen;
+                               memmove(p+1, thousands, bytelen);
+                       }
+                       *p-- = conv[i];
+                       n++;
+               }
+       }else{
+               while(u){
+                       i = u % base;
+                       u /= base;
+                       if((fl & FmtComma) && n % 4 == 3){
+                               *p-- = ',';
+                               n++;
+                       }
+                       if((fl & FmtApost) && __needsep(&ndig, &grouping)){
+                               n += len;
+                               excess += bytelen - len;
+                               p -= bytelen;
+                               memmove(p+1, thousands, bytelen);
+                       }
+                       *p-- = conv[i];
+                       n++;
+               }
+       }
+       if(n == 0){
+               /*
+                * "The result of converting a zero value with
+                * a precision of zero is no characters."  - ANSI
+                *
+                * "For o conversion, # increases the precision, if and only if
+                * necessary, to force the first digit of the result to be a zero
+                * (if the value and precision are both 0, a single 0 is printed)." - ANSI
+                */
+               if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))){
+                       *p-- = '0';
+                       n = 1;
+                       if(fl & FmtApost)
+                               __needsep(&ndig, &grouping);
+               }
+
+               /*
+                * Zero values don't get 0x.
+                */
+               if(f->r == 'x' || f->r == 'X')
+                       fl &= ~FmtSharp;
+       }
+       for(w = f->prec; n < w && p > buf+3; n++){
+               if((fl & FmtApost) && __needsep(&ndig, &grouping)){
+                       n += len;
+                       excess += bytelen - len;
+                       p -= bytelen;
+                       memmove(p+1, thousands, bytelen);
+               }
+               *p-- = '0';
+       }
+       if(neg || (fl & (FmtSign|FmtSpace)))
+               n++;
+       if(fl & FmtSharp){
+               if(base == 16)
+                       n += 2;
+               else if(base == 8){
+                       if(p[1] == '0')
+                               fl &= ~FmtSharp;
+                       else
+                               n++;
+               }
+       }
+       if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
+               w = 0;
+               if(fl & FmtWidth)
+                       w = f->width;
+               for(; n < w && p > buf+3; n++){
+                       if((fl & FmtApost) && __needsep(&ndig, &grouping)){
+                               n += len;
+                               excess += bytelen - len;
+                               p -= bytelen;
+                               memmove(p+1, thousands, bytelen);
+                       }
+                       *p-- = '0';
+               }
+               f->flags &= ~FmtWidth;
+       }
+       if(fl & FmtSharp){
+               if(base == 16)
+                       *p-- = f->r;
+               if(base == 16 || base == 8)
+                       *p-- = '0';
+       }
+       if(neg)
+               *p-- = '-';
+       else if(fl & FmtSign)
+               *p-- = '+';
+       else if(fl & FmtSpace)
+               *p-- = ' ';
+       f->flags &= ~FmtPrec;
+       return __fmtcpy(f, p + 1, n, n + excess);
+}
+
+int
+__countfmt(Fmt *f)
+{
+       void *p;
+       ulong fl;
+
+       fl = f->flags;
+       p = va_arg(f->args, void*);
+       if(fl & FmtVLong){
+               *(vlong*)p = f->nfmt;
+       }else if(fl & FmtLong){
+               *(long*)p = f->nfmt;
+       }else if(fl & FmtByte){
+               *(char*)p = f->nfmt;
+       }else if(fl & FmtShort){
+               *(short*)p = f->nfmt;
+       }else{
+               *(int*)p = f->nfmt;
+       }
+       return 0;
+}
+
+int
+__flagfmt(Fmt *f)
+{
+       switch(f->r){
+       case ',':
+               f->flags |= FmtComma;
+               break;
+       case '-':
+               f->flags |= FmtLeft;
+               break;
+       case '+':
+               f->flags |= FmtSign;
+               break;
+       case '#':
+               f->flags |= FmtSharp;
+               break;
+       case '\'':
+               f->flags |= FmtApost;
+               break;
+       case ' ':
+               f->flags |= FmtSpace;
+               break;
+       case 'u':
+               f->flags |= FmtUnsigned;
+               break;
+       case 'h':
+               if(f->flags & FmtShort)
+                       f->flags |= FmtByte;
+               f->flags |= FmtShort;
+               break;
+       case 'L':
+               f->flags |= FmtLDouble;
+               break;
+       case 'l':
+               if(f->flags & FmtLong)
+                       f->flags |= FmtVLong;
+               f->flags |= FmtLong;
+               break;
+       }
+       return 1;
+}
+
+/* default error format */
+int
+__badfmt(Fmt *f)
+{
+       char x[3];
+
+       x[0] = '%';
+       x[1] = f->r;
+       x[2] = '%';
+       f->prec = 3;
+       __fmtcpy(f, (const void*)x, 3, 3);
+       return 0;
+}
diff --git a/src/lib9/fmt/dorfmt.c b/src/lib9/fmt/dorfmt.c
new file mode 100644 (file)
index 0000000..672742f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/* format the output into f->to and return the number of characters fmted  */
+
+/* BUG: THIS FILE IS NOT UPDATED TO THE  NEW SPEC */
+int
+dorfmt(Fmt *f, const Rune *fmt)
+{
+       Rune *rt, *rs;
+       int r;
+       char *t, *s;
+       int nfmt;
+
+       nfmt = f->nfmt;
+       for(;;){
+               if(f->runes){
+                       rt = (Rune*)f->to;
+                       rs = (Rune*)f->stop;
+                       while((r = *fmt++) && r != '%'){
+                               FMTRCHAR(f, rt, rs, r);
+                       }
+                       f->nfmt += rt - (Rune *)f->to;
+                       f->to = rt;
+                       if(!r)
+                               return f->nfmt - nfmt;
+                       f->stop = rs;
+               }else{
+                       t = (char*)f->to;
+                       s = (char*)f->stop;
+                       while((r = *fmt++) && r != '%'){
+                               FMTRUNE(f, t, f->stop, r);
+                       }
+                       f->nfmt += t - (char *)f->to;
+                       f->to = t;
+                       if(!r)
+                               return f->nfmt - nfmt;
+                       f->stop = s;
+               }
+
+               fmt = (Rune*)__fmtdispatch(f, (Rune*)fmt, 1);
+               if(fmt == nil)
+                       return -1;
+       }
+       return 0;               /* not reached */
+}
diff --git a/src/lib9/fmt/errfmt.c b/src/lib9/fmt/errfmt.c
new file mode 100644 (file)
index 0000000..66c9600
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+__errfmt(Fmt *f)
+{
+       char *s;
+
+       s = strerror(errno);
+       return fmtstrcpy(f, s);
+}
diff --git a/src/lib9/fmt/fltfmt.c b/src/lib9/fmt/fltfmt.c
new file mode 100644 (file)
index 0000000..3ce8bab
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <errno.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+enum
+{
+       FDIGIT  = 30,
+       FDEFLT  = 6,
+       NSIGNIF = 17
+};
+
+/*
+ * first few powers of 10, enough for about 1/2 of the
+ * total space for doubles.
+ */
+static double pows10[] =
+{
+         1e0,   1e1,   1e2,   1e3,   1e4,   1e5,   1e6,   1e7,   1e8,   1e9,
+        1e10,  1e11,  1e12,  1e13,  1e14,  1e15,  1e16,  1e17,  1e18,  1e19,
+        1e20,  1e21,  1e22,  1e23,  1e24,  1e25,  1e26,  1e27,  1e28,  1e29,
+        1e30,  1e31,  1e32,  1e33,  1e34,  1e35,  1e36,  1e37,  1e38,  1e39,
+        1e40,  1e41,  1e42,  1e43,  1e44,  1e45,  1e46,  1e47,  1e48,  1e49,
+        1e50,  1e51,  1e52,  1e53,  1e54,  1e55,  1e56,  1e57,  1e58,  1e59,
+        1e60,  1e61,  1e62,  1e63,  1e64,  1e65,  1e66,  1e67,  1e68,  1e69,
+        1e70,  1e71,  1e72,  1e73,  1e74,  1e75,  1e76,  1e77,  1e78,  1e79,
+        1e80,  1e81,  1e82,  1e83,  1e84,  1e85,  1e86,  1e87,  1e88,  1e89,
+        1e90,  1e91,  1e92,  1e93,  1e94,  1e95,  1e96,  1e97,  1e98,  1e99,
+       1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
+       1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
+       1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
+       1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
+       1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
+       1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
+};
+#define        npows10 ((int)(sizeof(pows10)/sizeof(pows10[0])))
+#undef pow10
+#define pow10 fmtpow10
+
+static double
+pow10(int n)
+{
+       double d;
+       int neg;
+
+       neg = 0;
+       if(n < 0){
+               neg = 1;
+               n = -n;
+       }
+
+       if(n < npows10)
+               d = pows10[n];
+       else{
+               d = pows10[npows10-1];
+               for(;;){
+                       n -= npows10 - 1;
+                       if(n < npows10){
+                               d *= pows10[n];
+                               break;
+                       }
+                       d *= pows10[npows10 - 1];
+               }
+       }
+       if(neg)
+               return 1./d;
+       return d;
+}
+
+/*
+ * add 1 to the decimal integer string a of length n.
+ * if 99999 overflows into 10000, return 1 to tell caller
+ * to move the virtual decimal point.
+ */
+static int
+xadd1(char *a, int n)
+{
+       char *b;
+       int c;
+
+       if(n < 0 || n > NSIGNIF)
+               return 0;
+       for(b = a+n-1; b >= a; b--) {
+               c = *b + 1;
+               if(c <= '9') {
+                       *b = c;
+                       return 0;
+               }
+               *b = '0';
+       }
+       /*
+        * need to overflow adding digit.
+        * shift number down and insert 1 at beginning.
+        * decimal is known to be 0s or we wouldn't
+        * have gotten this far.  (e.g., 99999+1 => 00000)
+        */
+       a[0] = '1';
+       return 1;
+}
+
+/*
+ * subtract 1 from the decimal integer string a.
+ * if 10000 underflows into 09999, make it 99999
+ * and return 1 to tell caller to move the virtual
+ * decimal point.  this way, xsub1 is inverse of xadd1.
+ */
+static int
+xsub1(char *a, int n)
+{
+       char *b;
+       int c;
+
+       if(n < 0 || n > NSIGNIF)
+               return 0;
+       for(b = a+n-1; b >= a; b--) {
+               c = *b - 1;
+               if(c >= '0') {
+                       if(c == '0' && b == a) {
+                               /*
+                                * just zeroed the top digit; shift everyone up.
+                                * decimal is known to be 9s or we wouldn't
+                                * have gotten this far.  (e.g., 10000-1 => 09999)
+                                */
+                               *b = '9';
+                               return 1;
+                       }
+                       *b = c;
+                       return 0;
+               }
+               *b = '9';
+       }
+       /*
+        * can't get here.  the number a is always normalized
+        * so that it has a nonzero first digit.
+        */
+       abort();
+}
+
+/*
+ * format exponent like sprintf(p, "e%+02d", e)
+ */
+static void
+xfmtexp(char *p, int e, int ucase)
+{
+       char se[9];
+       int i;
+
+       *p++ = ucase ? 'E' : 'e';
+       if(e < 0) {
+               *p++ = '-';
+               e = -e;
+       } else
+               *p++ = '+';
+       i = 0;
+       while(e) {
+               se[i++] = e % 10 + '0';
+               e /= 10;
+       }
+       while(i < 2)
+               se[i++] = '0';
+       while(i > 0)
+               *p++ = se[--i];
+       *p++ = '\0';
+}
+
+/*
+ * compute decimal integer m, exp such that:
+ *     f = m*10^exp
+ *     m is as short as possible with losing exactness
+ * assumes special cases (NaN, +Inf, -Inf) have been handled.
+ */
+static void
+xdtoa(double f, char *s, int *exp, int *neg, int *ns)
+{
+       int c, d, e2, e, ee, i, ndigit, oerrno;
+       char tmp[NSIGNIF+10];
+       double g;
+
+       oerrno = errno; /* in case strtod smashes errno */
+
+       /*
+        * make f non-negative.
+        */
+       *neg = 0;
+       if(f < 0) {
+               f = -f;
+               *neg = 1;
+       }
+
+       /*
+        * must handle zero specially.
+        */
+       if(f == 0){
+               *exp = 0;
+               s[0] = '0';
+               s[1] = '\0';
+               *ns = 1;
+               return;
+       }
+
+       /*
+        * find g,e such that f = g*10^e.
+        * guess 10-exponent using 2-exponent, then fine tune.
+        */
+       frexp(f, &e2);
+       e = (int)(e2 * .301029995664);
+       g = f * pow10(-e);
+       while(g < 1) {
+               e--;
+               g = f * pow10(-e);
+       }
+       while(g >= 10) {
+               e++;
+               g = f * pow10(-e);
+       }
+
+       /*
+        * convert NSIGNIF digits as a first approximation.
+        */
+       for(i=0; i<NSIGNIF; i++) {
+               d = (int)g;
+               s[i] = d+'0';
+               g = (g-d) * 10;
+       }
+       s[i] = 0;
+
+       /*
+        * adjust e because s is 314159... not 3.14159...
+        */
+       e -= NSIGNIF-1;
+       xfmtexp(s+NSIGNIF, e, 0);
+
+       /*
+        * adjust conversion until strtod(s) == f exactly.
+        */
+       for(i=0; i<10; i++) {
+               g = strtod(s, nil);
+               if(f > g) {
+                       if(xadd1(s, NSIGNIF)) {
+                               /* gained a digit */
+                               e--;
+                               xfmtexp(s+NSIGNIF, e, 0);
+                       }
+                       continue;
+               }
+               if(f < g) {
+                       if(xsub1(s, NSIGNIF)) {
+                               /* lost a digit */
+                               e++;
+                               xfmtexp(s+NSIGNIF, e, 0);
+                       }
+                       continue;
+               }
+               break;
+       }
+
+       /*
+        * play with the decimal to try to simplify.
+        */
+
+       /*
+        * bump last few digits up to 9 if we can
+        */
+       for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
+               c = s[i];
+               if(c != '9') {
+                       s[i] = '9';
+                       g = strtod(s, nil);
+                       if(g != f) {
+                               s[i] = c;
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * add 1 in hopes of turning 9s to 0s
+        */
+       if(s[NSIGNIF-1] == '9') {
+               strcpy(tmp, s);
+               ee = e;
+               if(xadd1(tmp, NSIGNIF)) {
+                       ee--;
+                       xfmtexp(tmp+NSIGNIF, ee, 0);
+               }
+               g = strtod(tmp, nil);
+               if(g == f) {
+                       strcpy(s, tmp);
+                       e = ee;
+               }
+       }
+
+       /*
+        * bump last few digits down to 0 as we can.
+        */
+       for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
+               c = s[i];
+               if(c != '0') {
+                       s[i] = '0';
+                       g = strtod(s, nil);
+                       if(g != f) {
+                               s[i] = c;
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * remove trailing zeros.
+        */
+       ndigit = NSIGNIF;
+       while(ndigit > 1 && s[ndigit-1] == '0'){
+               e++;
+               --ndigit;
+       }
+       s[ndigit] = 0;
+       *exp = e;
+       *ns = ndigit;
+       errno = oerrno;
+}
+
+#ifdef PLAN9PORT
+static char *special[] = { "NaN", "NaN", "+Inf", "+Inf", "-Inf", "-Inf" };
+#else
+static char *special[] = { "nan", "NAN", "inf", "INF", "-inf", "-INF" };
+#endif
+
+int
+__efgfmt(Fmt *fmt)
+{
+       char buf[NSIGNIF+10], *dot, *digits, *p, *s, suf[10], *t;
+       double f;
+       int c, chr, dotwid, e, exp, fl, ndigits, neg, newndigits;
+       int pad, point, prec, realchr, sign, sufwid, ucase, wid, z1, z2;
+       Rune r, *rs, *rt;
+
+       if(fmt->flags&FmtLong)
+               f = va_arg(fmt->args, long double);
+       else
+               f = va_arg(fmt->args, double);
+
+       /*
+        * extract formatting flags
+        */
+       fl = fmt->flags;
+       fmt->flags = 0;
+       prec = FDEFLT;
+       if(fl & FmtPrec)
+               prec = fmt->prec;
+       chr = fmt->r;
+       ucase = 0;
+       switch(chr) {
+       case 'A':
+       case 'E':
+       case 'F':
+       case 'G':
+               chr += 'a'-'A';
+               ucase = 1;
+               break;
+       }
+
+       /*
+        * pick off special numbers.
+        */
+       if(__isNaN(f)) {
+               s = special[0+ucase];
+       special:
+               fmt->flags = fl & (FmtWidth|FmtLeft);
+               return __fmtcpy(fmt, s, strlen(s), strlen(s));
+       }
+       if(__isInf(f, 1)) {
+               s = special[2+ucase];
+               goto special;
+       }
+       if(__isInf(f, -1)) {
+               s = special[4+ucase];
+               goto special;
+       }
+
+       /*
+        * get exact representation.
+        */
+       digits = buf;
+       xdtoa(f, digits, &exp, &neg, &ndigits);
+
+       /*
+        * get locale's decimal point.
+        */
+       dot = fmt->decimal;
+       if(dot == nil)
+               dot = ".";
+       dotwid = utflen(dot);
+
+       /*
+        * now the formatting fun begins.
+        * compute parameters for actual fmt:
+        *
+        *      pad: number of spaces to insert before/after field.
+        *      z1: number of zeros to insert before digits
+        *      z2: number of zeros to insert after digits
+        *      point: number of digits to print before decimal point
+        *      ndigits: number of digits to use from digits[]
+        *      suf: trailing suffix, like "e-5"
+        */
+       realchr = chr;
+       switch(chr){
+       case 'g':
+               /*
+                * convert to at most prec significant digits. (prec=0 means 1)
+                */
+               if(prec == 0)
+                       prec = 1;
+               if(ndigits > prec) {
+                       if(digits[prec] >= '5' && xadd1(digits, prec))
+                               exp++;
+                       exp += ndigits-prec;
+                       ndigits = prec;
+               }
+
+               /*
+                * extra rules for %g (implemented below):
+                *      trailing zeros removed after decimal unless FmtSharp.
+                *      decimal point only if digit follows.
+                */
+
+               /* fall through to %e */
+       default:
+       case 'e':
+               /*
+                * one significant digit before decimal, no leading zeros.
+                */
+               point = 1;
+               z1 = 0;
+
+               /*
+                * decimal point is after ndigits digits right now.
+                * slide to be after first.
+                */
+               e  = exp + (ndigits-1);
+
+               /*
+                * if this is %g, check exponent and convert prec
+                */
+               if(realchr == 'g') {
+                       if(-4 <= e && e < prec)
+                               goto casef;
+                       prec--; /* one digit before decimal; rest after */
+               }
+
+               /*
+                * compute trailing zero padding or truncate digits.
+                */
+               if(1+prec >= ndigits)
+                       z2 = 1+prec - ndigits;
+               else {
+                       /*
+                        * truncate digits
+                        */
+                       assert(realchr != 'g');
+                       newndigits = 1+prec;
+                       if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
+                               /*
+                                * had 999e4, now have 100e5
+                                */
+                               e++;
+                       }
+                       ndigits = newndigits;
+                       z2 = 0;
+               }
+               xfmtexp(suf, e, ucase);
+               sufwid = strlen(suf);
+               break;
+
+       casef:
+       case 'f':
+               /*
+                * determine where digits go with respect to decimal point
+                */
+               if(ndigits+exp > 0) {
+                       point = ndigits+exp;
+                       z1 = 0;
+               } else {
+                       point = 1;
+                       z1 = 1 + -(ndigits+exp);
+               }
+
+               /*
+                * %g specifies prec = number of significant digits
+                * convert to number of digits after decimal point
+                */
+               if(realchr == 'g')
+                       prec += z1 - point;
+
+               /*
+                * compute trailing zero padding or truncate digits.
+                */
+               if(point+prec >= z1+ndigits)
+                       z2 = point+prec - (z1+ndigits);
+               else {
+                       /*
+                        * truncate digits
+                        */
+                       assert(realchr != 'g');
+                       newndigits = point+prec - z1;
+                       if(newndigits < 0) {
+                               z1 += newndigits;
+                               newndigits = 0;
+                       } else if(newndigits == 0) {
+                               /* perhaps round up */
+                               if(digits[0] >= '5'){
+                                       digits[0] = '1';
+                                       newndigits = 1;
+                                       goto newdigit;
+                               }
+                       } else if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
+                               /*
+                                * digits was 999, is now 100; make it 1000
+                                */
+                               digits[newndigits++] = '0';
+                       newdigit:
+                               /*
+                                * account for new digit
+                                */
+                               if(z1)  /* 0.099 => 0.100 or 0.99 => 1.00*/
+                                       z1--;
+                               else    /* 9.99 => 10.00 */
+                                       point++;
+                       }
+                       z2 = 0;
+                       ndigits = newndigits;
+               }
+               sufwid = 0;
+               break;
+       }
+
+       /*
+        * if %g is given without FmtSharp, remove trailing zeros.
+        * must do after truncation, so that e.g. print %.3g 1.001
+        * produces 1, not 1.00.  sorry, but them's the rules.
+        */
+       if(realchr == 'g' && !(fl & FmtSharp)) {
+               if(z1+ndigits+z2 >= point) {
+                       if(z1+ndigits < point)
+                               z2 = point - (z1+ndigits);
+                       else{
+                               z2 = 0;
+                               while(z1+ndigits > point && digits[ndigits-1] == '0')
+                                       ndigits--;
+                       }
+               }
+       }
+
+       /*
+        * compute width of all digits and decimal point and suffix if any
+        */
+       wid = z1+ndigits+z2;
+       if(wid > point)
+               wid += dotwid;
+       else if(wid == point){
+               if(fl & FmtSharp)
+                       wid += dotwid;
+               else
+                       point++;        /* do not print any decimal point */
+       }
+       wid += sufwid;
+
+       /*
+        * determine sign
+        */
+       sign = 0;
+       if(neg)
+               sign = '-';
+       else if(fl & FmtSign)
+               sign = '+';
+       else if(fl & FmtSpace)
+               sign = ' ';
+       if(sign)
+               wid++;
+
+       /*
+        * compute padding
+        */
+       pad = 0;
+       if((fl & FmtWidth) && fmt->width > wid)
+               pad = fmt->width - wid;
+       if(pad && !(fl & FmtLeft) && (fl & FmtZero)){
+               z1 += pad;
+               point += pad;
+               pad = 0;
+       }
+
+       /*
+        * format the actual field.  too bad about doing this twice.
+        */
+       if(fmt->runes){
+               if(pad && !(fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
+                       return -1;
+               rt = (Rune*)fmt->to;
+               rs = (Rune*)fmt->stop;
+               if(sign)
+                       FMTRCHAR(fmt, rt, rs, sign);
+               while(z1>0 || ndigits>0 || z2>0) {
+                       if(z1 > 0){
+                               z1--;
+                               c = '0';
+                       }else if(ndigits > 0){
+                               ndigits--;
+                               c = *digits++;
+                       }else{
+                               z2--;
+                               c = '0';
+                       }
+                       FMTRCHAR(fmt, rt, rs, c);
+                       if(--point == 0) {
+                               for(p = dot; *p; ){
+                                       p += chartorune(&r, p);
+                                       FMTRCHAR(fmt, rt, rs, r);
+                               }
+                       }
+               }
+               fmt->nfmt += rt - (Rune*)fmt->to;
+               fmt->to = rt;
+               if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
+                       return -1;
+               if(pad && (fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
+                       return -1;
+       }else{
+               if(pad && !(fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
+                       return -1;
+               t = (char*)fmt->to;
+               s = (char*)fmt->stop;
+               if(sign)
+                       FMTCHAR(fmt, t, s, sign);
+               while(z1>0 || ndigits>0 || z2>0) {
+                       if(z1 > 0){
+                               z1--;
+                               c = '0';
+                       }else if(ndigits > 0){
+                               ndigits--;
+                               c = *digits++;
+                       }else{
+                               z2--;
+                               c = '0';
+                       }
+                       FMTCHAR(fmt, t, s, c);
+                       if(--point == 0)
+                               for(p=dot; *p; p++)
+                                       FMTCHAR(fmt, t, s, *p);
+               }
+               fmt->nfmt += t - (char*)fmt->to;
+               fmt->to = t;
+               if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
+                       return -1;
+               if(pad && (fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
+                       return -1;
+       }
+       return 0;
+}
+
diff --git a/src/lib9/fmt/fmt.c b/src/lib9/fmt/fmt.c
new file mode 100644 (file)
index 0000000..7a747b1
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+enum
+{
+       Maxfmt = 64
+};
+
+typedef struct Convfmt Convfmt;
+struct Convfmt
+{
+       int     c;
+       volatile        Fmts    fmt;    /* for spin lock in fmtfmt; avoids race due to write order */
+};
+
+static struct
+{
+       /* lock by calling __fmtlock, __fmtunlock */
+       int     nfmt;
+       Convfmt fmt[Maxfmt];
+} fmtalloc;
+
+static Convfmt knownfmt[] = {
+       ' ',    __flagfmt,
+       '#',    __flagfmt,
+       '%',    __percentfmt,
+       '\'',   __flagfmt,
+       '+',    __flagfmt,
+       ',',    __flagfmt,
+       '-',    __flagfmt,
+       'C',    __runefmt,      /* Plan 9 addition */
+       'E',    __efgfmt,
+#ifndef PLAN9PORT
+       'F',    __efgfmt,       /* ANSI only */
+#endif
+       'G',    __efgfmt,
+#ifndef PLAN9PORT
+       'L',    __flagfmt,      /* ANSI only */
+#endif
+       'S',    __runesfmt,     /* Plan 9 addition */
+       'X',    __ifmt,
+       'b',    __ifmt,         /* Plan 9 addition */
+       'c',    __charfmt,
+       'd',    __ifmt,
+       'e',    __efgfmt,
+       'f',    __efgfmt,
+       'g',    __efgfmt,
+       'h',    __flagfmt,
+#ifndef PLAN9PORT
+       'i',    __ifmt,         /* ANSI only */
+#endif
+       'l',    __flagfmt,
+       'n',    __countfmt,
+       'o',    __ifmt,
+       'p',    __ifmt,
+       'r',    __errfmt,
+       's',    __strfmt,
+#ifdef PLAN9PORT
+       'u',    __flagfmt,
+#else
+       'u',    __ifmt,
+#endif
+       'x',    __ifmt,
+       0,      nil,
+};
+
+
+int    (*fmtdoquote)(int);
+
+/*
+ * __fmtlock() must be set
+ */
+static int
+__fmtinstall(int c, Fmts f)
+{
+       Convfmt *p, *ep;
+
+       if(c<=0 || c>=65536)
+               return -1;
+       if(!f)
+               f = __badfmt;
+
+       ep = &fmtalloc.fmt[fmtalloc.nfmt];
+       for(p=fmtalloc.fmt; p<ep; p++)
+               if(p->c == c)
+                       break;
+
+       if(p == &fmtalloc.fmt[Maxfmt])
+               return -1;
+
+       p->fmt = f;
+       if(p == ep){    /* installing a new format character */
+               fmtalloc.nfmt++;
+               p->c = c;
+       }
+
+       return 0;
+}
+
+int
+fmtinstall(int c, int (*f)(Fmt*))
+{
+       int ret;
+
+       __fmtlock();
+       ret = __fmtinstall(c, f);
+       __fmtunlock();
+       return ret;
+}
+
+static Fmts
+fmtfmt(int c)
+{
+       Convfmt *p, *ep;
+
+       ep = &fmtalloc.fmt[fmtalloc.nfmt];
+       for(p=fmtalloc.fmt; p<ep; p++)
+               if(p->c == c){
+                       while(p->fmt == nil)    /* loop until value is updated */
+                               ;
+                       return p->fmt;
+               }
+
+       /* is this a predefined format char? */
+       __fmtlock();
+       for(p=knownfmt; p->c; p++)
+               if(p->c == c){
+                       __fmtinstall(p->c, p->fmt);
+                       __fmtunlock();
+                       return p->fmt;
+               }
+       __fmtunlock();
+
+       return __badfmt;
+}
+
+void*
+__fmtdispatch(Fmt *f, void *fmt, int isrunes)
+{
+       Rune rune, r;
+       int i, n;
+
+       f->flags = 0;
+       f->width = f->prec = 0;
+
+       for(;;){
+               if(isrunes){
+                       r = *(Rune*)fmt;
+                       fmt = (Rune*)fmt + 1;
+               }else{
+                       fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
+                       r = rune;
+               }
+               f->r = r;
+               switch(r){
+               case '\0':
+                       return nil;
+               case '.':
+                       f->flags |= FmtWidth|FmtPrec;
+                       continue;
+               case '0':
+                       if(!(f->flags & FmtWidth)){
+                               f->flags |= FmtZero;
+                               continue;
+                       }
+                       /* fall through */
+               case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                       i = 0;
+                       while(r >= '0' && r <= '9'){
+                               i = i * 10 + r - '0';
+                               if(isrunes){
+                                       r = *(Rune*)fmt;
+                                       fmt = (Rune*)fmt + 1;
+                               }else{
+                                       r = *(char*)fmt;
+                                       fmt = (char*)fmt + 1;
+                               }
+                       }
+                       if(isrunes)
+                               fmt = (Rune*)fmt - 1;
+                       else
+                               fmt = (char*)fmt - 1;
+               numflag:
+                       if(f->flags & FmtWidth){
+                               f->flags |= FmtPrec;
+                               f->prec = i;
+                       }else{
+                               f->flags |= FmtWidth;
+                               f->width = i;
+                       }
+                       continue;
+               case '*':
+                       i = va_arg(f->args, int);
+                       if(i < 0){
+                               /*
+                                * negative precision =>
+                                * ignore the precision.
+                                */
+                               if(f->flags & FmtPrec){
+                                       f->flags &= ~FmtPrec;
+                                       f->prec = 0;
+                                       continue;
+                               }
+                               i = -i;
+                               f->flags |= FmtLeft;
+                       }
+                       goto numflag;
+               }
+               n = (*fmtfmt(r))(f);
+               if(n < 0)
+                       return nil;
+               if(n == 0)
+                       return fmt;
+       }
+}
diff --git a/src/lib9/fmt/fmtdef.h b/src/lib9/fmt/fmtdef.h
new file mode 100644 (file)
index 0000000..74cb8a8
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/*
+ * dofmt -- format to a buffer
+ * the number of characters formatted is returned,
+ * or -1 if there was an error.
+ * if the buffer is ever filled, flush is called.
+ * it should reset the buffer and return whether formatting should continue.
+ */
+
+typedef int (*Fmts)(Fmt*);
+
+typedef struct Quoteinfo Quoteinfo;
+struct Quoteinfo
+{
+       int     quoted;         /* if set, string must be quoted */
+       int     nrunesin;       /* number of input runes that can be accepted */
+       int     nbytesin;       /* number of input bytes that can be accepted */
+       int     nrunesout;      /* number of runes that will be generated */
+       int     nbytesout;      /* number of bytes that will be generated */
+};
+
+/* Edit .+1,/^$/ |cfn |grep -v static | grep __ */
+double       __Inf(int sign);
+double       __NaN(void);
+int          __badfmt(Fmt *f);
+int          __charfmt(Fmt *f);
+int          __countfmt(Fmt *f);
+int          __efgfmt(Fmt *fmt);
+int          __errfmt(Fmt *f);
+int          __flagfmt(Fmt *f);
+int          __fmtFdFlush(Fmt *f);
+int          __fmtcpy(Fmt *f, const void *vm, int n, int sz);
+void*        __fmtdispatch(Fmt *f, void *fmt, int isrunes);
+void *       __fmtflush(Fmt *f, void *t, int len);
+void         __fmtlock(void);
+int          __fmtpad(Fmt *f, int n);
+double       __fmtpow10(int n);
+int          __fmtrcpy(Fmt *f, const void *vm, int n);
+void         __fmtunlock(void);
+int          __ifmt(Fmt *f);
+int          __isInf(double d, int sign);
+int          __isNaN(double d);
+int          __needsep(int*, char**);
+int          __needsquotes(char *s, int *quotelenp);
+int          __percentfmt(Fmt *f);
+void         __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout);
+int          __quotestrfmt(int runesin, Fmt *f);
+int          __rfmtpad(Fmt *f, int n);
+int          __runefmt(Fmt *f);
+int          __runeneedsquotes(Rune *r, int *quotelenp);
+int          __runesfmt(Fmt *f);
+int          __strfmt(Fmt *f);
+
+#define FMTCHAR(f, t, s, c)\
+       do{\
+       if(t + 1 > (char*)s){\
+               t = (char*)__fmtflush(f, t, 1);\
+               if(t != nil)\
+                       s = (char*)f->stop;\
+               else\
+                       return -1;\
+       }\
+       *t++ = c;\
+       }while(0)
+
+#define FMTRCHAR(f, t, s, c)\
+       do{\
+       if(t + 1 > (Rune*)s){\
+               t = (Rune*)__fmtflush(f, t, sizeof(Rune));\
+               if(t != nil)\
+                       s = (Rune*)f->stop;\
+               else\
+                       return -1;\
+       }\
+       *t++ = c;\
+       }while(0)
+
+#define FMTRUNE(f, t, s, r)\
+       do{\
+       Rune _rune;\
+       int _runelen;\
+       if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\
+               t = (char*)__fmtflush(f, t, _runelen);\
+               if(t != nil)\
+                       s = (char*)f->stop;\
+               else\
+                       return -1;\
+       }\
+       if(r < Runeself)\
+               *t++ = r;\
+       else{\
+               _rune = r;\
+               t += runetochar(t, &_rune);\
+       }\
+       }while(0)
+
+#ifdef va_copy
+#      define VA_COPY(a,b) va_copy(a,b)
+#      define VA_END(a) va_end(a)
+#else
+#      define VA_COPY(a,b) (a) = (b)
+#      define VA_END(a)
+#endif
+
diff --git a/src/lib9/fmt/fmtfd.c b/src/lib9/fmt/fmtfd.c
new file mode 100644 (file)
index 0000000..c32abf1
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * public routine for final flush of a formatting buffer
+ * to a file descriptor; returns total char count.
+ */
+int
+fmtfdflush(Fmt *f)
+{
+       if(__fmtFdFlush(f) <= 0)
+               return -1;
+       return f->nfmt;
+}
+
+/*
+ * initialize an output buffer for buffered printing
+ */
+int
+fmtfdinit(Fmt *f, int fd, char *buf, int size)
+{
+       f->runes = 0;
+       f->start = buf;
+       f->to = buf;
+       f->stop = buf + size;
+       f->flush = __fmtFdFlush;
+       f->farg = (void*)(uintptr_t)fd;
+       f->flags = 0;
+       f->nfmt = 0;
+       fmtlocaleinit(f, nil, nil, nil);
+       return 0;
+}
diff --git a/src/lib9/fmt/fmtfdflush.c b/src/lib9/fmt/fmtfdflush.c
new file mode 100644 (file)
index 0000000..c9854ce
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * generic routine for flushing a formatting buffer
+ * to a file descriptor
+ */
+int
+__fmtFdFlush(Fmt *f)
+{
+       int n;
+
+       n = (char*)f->to - (char*)f->start;
+       if(n && write((uintptr)f->farg, f->start, n) != n)
+               return 0;
+       f->to = f->start;
+       return 1;
+}
diff --git a/src/lib9/fmt/fmtlocale.c b/src/lib9/fmt/fmtlocale.c
new file mode 100644 (file)
index 0000000..64ed10f
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * Fill in the internationalization stuff in the State structure.
+ * For nil arguments, provide the sensible defaults:
+ *     decimal is a period
+ *     thousands separator is a comma
+ *     thousands are marked every three digits
+ */
+void
+fmtlocaleinit(Fmt *f, char *decimal, char *thousands, char *grouping)
+{
+       if(decimal == nil || decimal[0] == '\0')
+               decimal = ".";
+       if(thousands == nil)
+               thousands = ",";
+       if(grouping == nil)
+               grouping = "\3";
+       f->decimal = decimal;
+       f->thousands = thousands;
+       f->grouping = grouping;
+}
+
+/*
+ * We are about to emit a digit in e.g. %'d.  If that digit would
+ * overflow a thousands (e.g.) grouping, tell the caller to emit
+ * the thousands separator.  Always advance the digit counter
+ * and pointer into the grouping descriptor.
+ */
+int
+__needsep(int *ndig, char **grouping)
+{
+       int group;
+
+       (*ndig)++;
+       group = *(unsigned char*)*grouping;
+       /* CHAR_MAX means no further grouping. \0 means we got the empty string */
+       if(group == 0xFF || group == 0x7f || group == 0x00)
+               return 0;
+       if(*ndig > group){
+               /* if we're at end of string, continue with this grouping; else advance */
+               if((*grouping)[1] != '\0')
+                       (*grouping)++;
+               *ndig = 1;
+               return 1;
+       }
+       return 0;
+}
+
diff --git a/src/lib9/fmt/fmtlock.c b/src/lib9/fmt/fmtlock.c
new file mode 100644 (file)
index 0000000..297acd8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+void
+__fmtlock(void)
+{
+}
+
+void
+__fmtunlock(void)
+{
+}
diff --git a/src/lib9/fmt/fmtnull.c b/src/lib9/fmt/fmtnull.c
new file mode 100644 (file)
index 0000000..b8caacb
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * Absorb output without using resources.
+ */
+static Rune nullbuf[32];
+
+static int
+__fmtnullflush(Fmt *f)
+{
+       f->to = nullbuf;
+       f->nfmt = 0;
+       return 0;
+}
+
+int
+fmtnullinit(Fmt *f)
+{
+       memset(f, 0, sizeof *f);
+       f->runes = 1;
+       f->start = nullbuf;
+       f->to = nullbuf;
+       f->stop = nullbuf+nelem(nullbuf);
+       f->flush = __fmtnullflush;
+       fmtlocaleinit(f, nil, nil, nil);
+       return 0;
+}
+
diff --git a/src/lib9/fmt/fmtprint.c b/src/lib9/fmt/fmtprint.c
new file mode 100644 (file)
index 0000000..8a29e6f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * format a string into the output buffer
+ * designed for formats which themselves call fmt,
+ * but ignore any width flags
+ */
+int
+fmtprint(Fmt *f, char *fmt, ...)
+{
+       va_list va;
+       int n;
+
+       f->flags = 0;
+       f->width = 0;
+       f->prec = 0;
+       VA_COPY(va, f->args);
+       VA_END(f->args);
+       va_start(f->args, fmt);
+       n = dofmt(f, fmt);
+       va_end(f->args);
+       f->flags = 0;
+       f->width = 0;
+       f->prec = 0;
+       VA_COPY(f->args,va);
+       VA_END(va);
+       if(n >= 0)
+               return 0;
+       return n;
+}
+
diff --git a/src/lib9/fmt/fmtquote.c b/src/lib9/fmt/fmtquote.c
new file mode 100644 (file)
index 0000000..b9ac772
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * How many bytes of output UTF will be produced by quoting (if necessary) this string?
+ * How many runes? How much of the input will be consumed?
+ * The parameter q is filled in by __quotesetup.
+ * The string may be UTF or Runes (s or r).
+ * Return count does not include NUL.
+ * Terminate the scan at the first of:
+ *     NUL in input
+ *     count exceeded in input
+ *     count exceeded on output
+ * *ninp is set to number of input bytes accepted.
+ * nin may be <0 initially, to avoid checking input by count.
+ */
+void
+__quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout)
+{
+       int w;
+       Rune c;
+
+       q->quoted = 0;
+       q->nbytesout = 0;
+       q->nrunesout = 0;
+       q->nbytesin = 0;
+       q->nrunesin = 0;
+       if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){
+               if(nout < 2)
+                       return;
+               q->quoted = 1;
+               q->nbytesout = 2;
+               q->nrunesout = 2;
+       }
+       for(; nin!=0; nin--){
+               if(s)
+                       w = chartorune(&c, s);
+               else{
+                       c = *r;
+                       w = runelen(c);
+               }
+
+               if(c == '\0')
+                       break;
+               if(runesout){
+                       if(q->nrunesout+1 > nout)
+                               break;
+               }else{
+                       if(q->nbytesout+w > nout)
+                               break;
+               }
+
+               if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){
+                       if(!q->quoted){
+                               if(runesout){
+                                       if(1+q->nrunesout+1+1 > nout)   /* no room for quotes */
+                                               break;
+                               }else{
+                                       if(1+q->nbytesout+w+1 > nout)   /* no room for quotes */
+                                               break;
+                               }
+                               q->nrunesout += 2;      /* include quotes */
+                               q->nbytesout += 2;      /* include quotes */
+                               q->quoted = 1;
+                       }
+                       if(c == '\'')   {
+                               if(runesout){
+                                       if(1+q->nrunesout+1 > nout)     /* no room for quotes */
+                                               break;
+                               }else{
+                                       if(1+q->nbytesout+w > nout)     /* no room for quotes */
+                                               break;
+                               }
+                               q->nbytesout++;
+                               q->nrunesout++; /* quotes reproduce as two characters */
+                       }
+               }
+
+               /* advance input */
+               if(s)
+                       s += w;
+               else
+                       r++;
+               q->nbytesin += w;
+               q->nrunesin++;
+
+               /* advance output */
+               q->nbytesout += w;
+               q->nrunesout++;
+
+#ifndef PLAN9PORT
+               /* ANSI requires precision in bytes, not Runes. */
+               nin-= w-1;      /* and then n-- in the loop */
+#endif
+       }
+}
+
+static int
+qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f)
+{
+       Rune r, *rm, *rme;
+       char *t, *s, *m, *me;
+       Rune *rt, *rs;
+       ulong fl;
+       int nc, w;
+
+       m = sin;
+       me = m + q->nbytesin;
+       rm = rin;
+       rme = rm + q->nrunesin;
+
+       fl = f->flags;
+       w = 0;
+       if(fl & FmtWidth)
+               w = f->width;
+       if(f->runes){
+               if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0)
+                       return -1;
+       }else{
+               if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
+                       return -1;
+       }
+       t = (char*)f->to;
+       s = (char*)f->stop;
+       rt = (Rune*)f->to;
+       rs = (Rune*)f->stop;
+       if(f->runes)
+               FMTRCHAR(f, rt, rs, '\'');
+       else
+               FMTRUNE(f, t, s, '\'');
+       for(nc = q->nrunesin; nc > 0; nc--){
+               if(sin){
+                       r = *(uchar*)m;
+                       if(r < Runeself)
+                               m++;
+                       else if((me - m) >= UTFmax || fullrune(m, me-m))
+                               m += chartorune(&r, m);
+                       else
+                               break;
+               }else{
+                       if(rm >= rme)
+                               break;
+                       r = *(uchar*)rm++;
+               }
+               if(f->runes){
+                       FMTRCHAR(f, rt, rs, r);
+                       if(r == '\'')
+                               FMTRCHAR(f, rt, rs, r);
+               }else{
+                       FMTRUNE(f, t, s, r);
+                       if(r == '\'')
+                               FMTRUNE(f, t, s, r);
+               }
+       }
+
+       if(f->runes){
+               FMTRCHAR(f, rt, rs, '\'');
+               USED(rs);
+               f->nfmt += rt - (Rune *)f->to;
+               f->to = rt;
+               if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0)
+                       return -1;
+       }else{
+               FMTRUNE(f, t, s, '\'');
+               USED(s);
+               f->nfmt += t - (char *)f->to;
+               f->to = t;
+               if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
+                       return -1;
+       }
+       return 0;
+}
+
+int
+__quotestrfmt(int runesin, Fmt *f)
+{
+       int nin, outlen;
+       Rune *r;
+       char *s;
+       Quoteinfo q;
+
+       nin = -1;
+       if(f->flags&FmtPrec)
+               nin = f->prec;
+       if(runesin){
+               r = va_arg(f->args, Rune *);
+               s = nil;
+       }else{
+               s = va_arg(f->args, char *);
+               r = nil;
+       }
+       if(!s && !r)
+               return __fmtcpy(f, (void*)"<nil>", 5, 5);
+
+       if(f->flush)
+               outlen = 0x7FFFFFFF;    /* if we can flush, no output limit */
+       else if(f->runes)
+               outlen = (Rune*)f->stop - (Rune*)f->to;
+       else
+               outlen = (char*)f->stop - (char*)f->to;
+
+       __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes);
+/*print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); */
+
+       if(runesin){
+               if(!q.quoted)
+                       return __fmtrcpy(f, r, q.nrunesin);
+               return qstrfmt(nil, r, &q, f);
+       }
+
+       if(!q.quoted)
+               return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
+       return qstrfmt(s, nil, &q, f);
+}
+
+int
+quotestrfmt(Fmt *f)
+{
+       return __quotestrfmt(0, f);
+}
+
+int
+quoterunestrfmt(Fmt *f)
+{
+       return __quotestrfmt(1, f);
+}
+
+void
+quotefmtinstall(void)
+{
+       fmtinstall('q', quotestrfmt);
+       fmtinstall('Q', quoterunestrfmt);
+}
+
+int
+__needsquotes(char *s, int *quotelenp)
+{
+       Quoteinfo q;
+
+       __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
+       *quotelenp = q.nbytesout;
+
+       return q.quoted;
+}
+
+int
+__runeneedsquotes(Rune *r, int *quotelenp)
+{
+       Quoteinfo q;
+
+       __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
+       *quotelenp = q.nrunesout;
+
+       return q.quoted;
+}
diff --git a/src/lib9/fmt/fmtrune.c b/src/lib9/fmt/fmtrune.c
new file mode 100644 (file)
index 0000000..da8c5d7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+fmtrune(Fmt *f, int r)
+{
+       Rune *rt;
+       char *t;
+       int n;
+
+       if(f->runes){
+               rt = (Rune*)f->to;
+               FMTRCHAR(f, rt, f->stop, r);
+               f->to = rt;
+               n = 1;
+       }else{
+               t = (char*)f->to;
+               FMTRUNE(f, t, f->stop, r);
+               n = t - (char*)f->to;
+               f->to = t;
+       }
+       f->nfmt += n;
+       return 0;
+}
diff --git a/src/lib9/fmt/fmtstr.c b/src/lib9/fmt/fmtstr.c
new file mode 100644 (file)
index 0000000..a6ca772
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+char*
+fmtstrflush(Fmt *f)
+{
+       if(f->start == nil)
+               return nil;
+       *(char*)f->to = '\0';
+       f->to = f->start;
+       return (char*)f->start;
+}
diff --git a/src/lib9/fmt/fmtvprint.c b/src/lib9/fmt/fmtvprint.c
new file mode 100644 (file)
index 0000000..6acd37a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+
+/*
+ * format a string into the output buffer
+ * designed for formats which themselves call fmt,
+ * but ignore any width flags
+ */
+int
+fmtvprint(Fmt *f, char *fmt, va_list args)
+{
+       va_list va;
+       int n;
+
+       f->flags = 0;
+       f->width = 0;
+       f->prec = 0;
+       VA_COPY(va,f->args);
+       VA_END(f->args);
+       VA_COPY(f->args,args);
+       n = dofmt(f, fmt);
+       f->flags = 0;
+       f->width = 0;
+       f->prec = 0;
+       VA_END(f->args);
+       VA_COPY(f->args,va);
+       VA_END(va);
+       if(n >= 0)
+               return 0;
+       return n;
+}
+
diff --git a/src/lib9/fmt/fprint.c b/src/lib9/fmt/fprint.c
new file mode 100644 (file)
index 0000000..70cb138
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+fprint(int fd, char *fmt, ...)
+{
+       int n;
+       va_list args;
+
+       va_start(args, fmt);
+       n = vfprint(fd, fmt, args);
+       va_end(args);
+       return n;
+}
diff --git a/src/lib9/fmt/nan64.c b/src/lib9/fmt/nan64.c
new file mode 100644 (file)
index 0000000..1ea7027
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/*
+ * 64-bit IEEE not-a-number routines.
+ * This is big/little-endian portable assuming that
+ * the 64-bit doubles and 64-bit integers have the
+ * same byte ordering.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+static uvlong uvnan    = ((uvlong)0x7FF00000<<32)|0x00000001;
+static uvlong uvinf    = ((uvlong)0x7FF00000<<32)|0x00000000;
+static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000;
+
+/* gcc sees through the obvious casts. */
+static uvlong
+d2u(double d)
+{
+       union {
+               uvlong v;
+               double d;
+       } u;
+       assert(sizeof(u.d) == sizeof(u.v));
+       u.d = d;
+       return u.v;
+}
+
+static double
+u2d(uvlong v)
+{
+       union {
+               uvlong v;
+               double d;
+       } u;
+       assert(sizeof(u.d) == sizeof(u.v));
+       u.v = v;
+       return u.d;
+}
+
+double
+__NaN(void)
+{
+       return u2d(uvnan);
+}
+
+int
+__isNaN(double d)
+{
+       uvlong x;
+
+       x = d2u(d);
+       /* IEEE 754: exponent bits 0x7FF and non-zero mantissa */
+       return (x&uvinf) == uvinf && (x&~uvneginf) != 0;
+}
+
+double
+__Inf(int sign)
+{
+       return u2d(sign < 0 ? uvneginf : uvinf);
+}
+
+int
+__isInf(double d, int sign)
+{
+       uvlong x;
+
+       x = d2u(d);
+       if(sign == 0)
+               return x==uvinf || x==uvneginf;
+       else if(sign > 0)
+               return x==uvinf;
+       else
+               return x==uvneginf;
+}
diff --git a/src/lib9/fmt/pow10.c b/src/lib9/fmt/pow10.c
new file mode 100644 (file)
index 0000000..e146884
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+/*
+ * this table might overflow 127-bit exponent representations.
+ * in that case, truncate it after 1.0e38.
+ * it is important to get all one can from this
+ * routine since it is used in atof to scale numbers.
+ * the presumption is that C converts fp numbers better
+ * than multipication of lower powers of 10.
+ */
+
+static
+double tab[] =
+{
+       1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
+       1.0e10,1.0e11,1.0e12,1.0e13,1.0e14,1.0e15,1.0e16,1.0e17,1.0e18,1.0e19,
+       1.0e20,1.0e21,1.0e22,1.0e23,1.0e24,1.0e25,1.0e26,1.0e27,1.0e28,1.0e29,
+       1.0e30,1.0e31,1.0e32,1.0e33,1.0e34,1.0e35,1.0e36,1.0e37,1.0e38,1.0e39,
+       1.0e40,1.0e41,1.0e42,1.0e43,1.0e44,1.0e45,1.0e46,1.0e47,1.0e48,1.0e49,
+       1.0e50,1.0e51,1.0e52,1.0e53,1.0e54,1.0e55,1.0e56,1.0e57,1.0e58,1.0e59,
+       1.0e60,1.0e61,1.0e62,1.0e63,1.0e64,1.0e65,1.0e66,1.0e67,1.0e68,1.0e69,
+};
+
+double
+__fmtpow10(int n)
+{
+       int m;
+
+       if(n < 0) {
+               n = -n;
+               if(n < (int)(sizeof(tab)/sizeof(tab[0])))
+                       return 1/tab[n];
+               m = n/2;
+               return __fmtpow10(-m) * __fmtpow10(m-n);
+       }
+       if(n < (int)(sizeof(tab)/sizeof(tab[0])))
+               return tab[n];
+       m = n/2;
+       return __fmtpow10(m) * __fmtpow10(n-m);
+}
diff --git a/src/lib9/fmt/print.c b/src/lib9/fmt/print.c
new file mode 100644 (file)
index 0000000..5c39457
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+print(char *fmt, ...)
+{
+       int n;
+       va_list args;
+
+       va_start(args, fmt);
+       n = vfprint(1, fmt, args);
+       va_end(args);
+       return n;
+}
diff --git a/src/lib9/fmt/seprint.c b/src/lib9/fmt/seprint.c
new file mode 100644 (file)
index 0000000..88779d9
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+char*
+seprint(char *buf, char *e, char *fmt, ...)
+{
+       char *p;
+       va_list args;
+
+       va_start(args, fmt);
+       p = vseprint(buf, e, fmt, args);
+       va_end(args);
+       return p;
+}
diff --git a/src/lib9/fmt/smprint.c b/src/lib9/fmt/smprint.c
new file mode 100644 (file)
index 0000000..c13ffd7
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+char*
+smprint(char *fmt, ...)
+{
+       va_list args;
+       char *p;
+
+       va_start(args, fmt);
+       p = vsmprint(fmt, args);
+       va_end(args);
+       return p;
+}
diff --git a/src/lib9/fmt/snprint.c b/src/lib9/fmt/snprint.c
new file mode 100644 (file)
index 0000000..372399c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+snprint(char *buf, int len, char *fmt, ...)
+{
+       int n;
+       va_list args;
+
+       va_start(args, fmt);
+       n = vsnprint(buf, len, fmt, args);
+       va_end(args);
+       return n;
+}
+
diff --git a/src/lib9/fmt/sprint.c b/src/lib9/fmt/sprint.c
new file mode 100644 (file)
index 0000000..38d4307
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+sprint(char *buf, char *fmt, ...)
+{
+       int n;
+       uint len;
+       va_list args;
+
+       len = 1<<30;  /* big number, but sprint is deprecated anyway */
+       /*
+        * on PowerPC, the stack is near the top of memory, so
+        * we must be sure not to overflow a 32-bit pointer.
+        *
+        * careful!  gcc-4.2 assumes buf+len < buf can never be true and
+        * optimizes the test away.  casting to uintptr works around this bug.
+        */
+       if((uintptr)buf+len < (uintptr)buf)
+               len = -(uintptr)buf-1;
+
+       va_start(args, fmt);
+       n = vsnprint(buf, len, fmt, args);
+       va_end(args);
+       return n;
+}
diff --git a/src/lib9/fmt/test.c b/src/lib9/fmt/test.c
new file mode 100644 (file)
index 0000000..1710c5e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+main(int argc, char *argv[])
+{
+       quotefmtinstall();
+       print("hello world\n");
+       print("x: %x\n", 0x87654321);
+       print("u: %u\n", 0x87654321);
+       print("d: %d\n", 0x87654321);
+       print("s: %s\n", "hi there");
+       print("q: %q\n", "hi i'm here");
+       print("c: %c\n", '!');
+       print("g: %g %g %g\n", 3.14159, 3.14159e10, 3.14159e-10);
+       print("e: %e %e %e\n", 3.14159, 3.14159e10, 3.14159e-10);
+       print("f: %f %f %f\n", 3.14159, 3.14159e10, 3.14159e-10);
+       print("smiley: %C\n", (Rune)0x263a);
+       print("%g %.18g\n", 2e25, 2e25);
+       print("%2.18g\n", 1.0);
+       print("%2.18f\n", 1.0);
+       print("%f\n", 3.1415927/4);
+       print("%d\n", 23);
+       print("%i\n", 23);
+       print("%0.10d\n", 12345);
+
+       /* test %4$d formats */
+       print("%3$d %4$06d %2$d %1$d\n", 444, 333, 111, 222);
+       print("%3$d %4$06d %2$d %1$d\n", 444, 333, 111, 222);
+       print("%3$d %4$*5$06d %2$d %1$d\n", 444, 333, 111, 222, 20);
+       print("%3$hd %4$*5$06d %2$d %1$d\n", 444, 333, (short)111, 222, 20);
+       print("%3$lld %4$*5$06d %2$d %1$d\n", 444, 333, 111LL, 222, 20);
+
+       /* test %'d formats */
+       print("%'d %'d %'d\n", 1, 2222, 33333333);
+       print("%'019d\n", 0);
+       print("%08d %08d %08d\n", 1, 2222, 33333333);
+       print("%'08d %'08d %'08d\n", 1, 2222, 33333333);
+       print("%'x %'X %'b\n", 0x11111111, 0xabcd1234, 12345);
+       print("%'lld %'lld %'lld\n", 1LL, 222222222LL, 3333333333333LL);
+       print("%019lld %019lld %019lld\n", 1LL, 222222222LL, 3333333333333LL);
+       print("%'019lld %'019lld %'019lld\n", 1LL, 222222222LL, 3333333333333LL);
+       print("%'020lld %'020lld %'020lld\n", 1LL, 222222222LL, 3333333333333LL);
+       print("%'llx %'llX %'llb\n", 0x111111111111LL, 0xabcd12345678LL, 112342345LL);
+       return 0;
+}
diff --git a/src/lib9/fmt/vfprint.c b/src/lib9/fmt/vfprint.c
new file mode 100644 (file)
index 0000000..a23c5a0
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+vfprint(int fd, char *fmt, va_list args)
+{
+       Fmt f;
+       char buf[256];
+       int n;
+
+       fmtfdinit(&f, fd, buf, sizeof(buf));
+       VA_COPY(f.args,args);
+       n = dofmt(&f, fmt);
+       VA_END(f.args);
+       if(n > 0 && __fmtFdFlush(&f) == 0)
+               return -1;
+       return n;
+}
diff --git a/src/lib9/fmt/vseprint.c b/src/lib9/fmt/vseprint.c
new file mode 100644 (file)
index 0000000..c9fbfb9
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+char*
+vseprint(char *buf, char *e, char *fmt, va_list args)
+{
+       Fmt f;
+
+       if(e <= buf)
+               return nil;
+       f.runes = 0;
+       f.start = buf;
+       f.to = buf;
+       f.stop = e - 1;
+       f.flush = 0;
+       f.farg = nil;
+       f.nfmt = 0;
+       VA_COPY(f.args,args);
+       fmtlocaleinit(&f, nil, nil, nil);
+       dofmt(&f, fmt);
+       VA_END(f.args);
+       *(char*)f.to = '\0';
+       return (char*)f.to;
+}
+
diff --git a/src/lib9/fmt/vsmprint.c b/src/lib9/fmt/vsmprint.c
new file mode 100644 (file)
index 0000000..4bd0bc4
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+static int
+fmtStrFlush(Fmt *f)
+{
+       char *s;
+       int n;
+
+       if(f->start == nil)
+               return 0;
+       n = (uintptr)f->farg;
+       n *= 2;
+       s = (char*)f->start;
+       f->start = realloc(s, n);
+       if(f->start == nil){
+               f->farg = nil;
+               f->to = nil;
+               f->stop = nil;
+               free(s);
+               return 0;
+       }
+       f->farg = (void*)(uintptr)n;
+       f->to = (char*)f->start + ((char*)f->to - s);
+       f->stop = (char*)f->start + n - 1;
+       return 1;
+}
+
+int
+fmtstrinit(Fmt *f)
+{
+       int n;
+
+       memset(f, 0, sizeof *f);
+       f->runes = 0;
+       n = 32;
+       f->start = malloc(n);
+       if(f->start == nil)
+               return -1;
+       f->to = f->start;
+       f->stop = (char*)f->start + n - 1;
+       f->flush = fmtStrFlush;
+       f->farg = (void*)(uintptr)n;
+       f->nfmt = 0;
+       fmtlocaleinit(f, nil, nil, nil);
+       return 0;
+}
+
+/*
+ * print into an allocated string buffer
+ */
+char*
+vsmprint(char *fmt, va_list args)
+{
+       Fmt f;
+       int n;
+
+       if(fmtstrinit(&f) < 0)
+               return nil;
+       VA_COPY(f.args,args);
+       n = dofmt(&f, fmt);
+       VA_END(f.args);
+       if(n < 0){
+               free(f.start);
+               return nil;
+       }
+       return fmtstrflush(&f);
+}
diff --git a/src/lib9/fmt/vsnprint.c b/src/lib9/fmt/vsnprint.c
new file mode 100644 (file)
index 0000000..33d6bba
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson,
+ * with contributions from Mike Burrows and Sean Dorward.
+ *
+ *     Copyright (c) 2002-2006 by Lucent Technologies.
+ *     Portions Copyright (c) 2004 Google Inc.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
+ * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
+ * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include "fmtdef.h"
+
+int
+vsnprint(char *buf, int len, char *fmt, va_list args)
+{
+       Fmt f;
+
+       if(len <= 0)
+               return -1;
+       f.runes = 0;
+       f.start = buf;
+       f.to = buf;
+       f.stop = buf + len - 1;
+       f.flush = 0;
+       f.farg = nil;
+       f.nfmt = 0;
+       VA_COPY(f.args,args);
+       fmtlocaleinit(&f, nil, nil, nil);
+       dofmt(&f, fmt);
+       VA_END(f.args);
+       *(char*)f.to = '\0';
+       return (char*)f.to - buf;
+}
diff --git a/src/lib9/fmtlock2.c b/src/lib9/fmtlock2.c
new file mode 100644 (file)
index 0000000..75406b5
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+Plan 9 from User Space src/lib9/fmtlock2.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/fmtlock2.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+Portions Copyright 2009 The Go Authors.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+void
+__fmtlock(void)
+{
+}
+
+void
+__fmtunlock(void)
+{
+}
diff --git a/src/lib9/fork.c b/src/lib9/fork.c
new file mode 100644 (file)
index 0000000..0dd79df
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+Plan 9 from User Space src/lib9/fork.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/fork.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#include <signal.h>
+#include <libc.h>
+#include "9proc.h"
+#undef fork
+
+int
+p9fork(void)
+{
+       int pid;
+       sigset_t all, old;
+
+       sigfillset(&all);
+       sigprocmask(SIG_SETMASK, &all, &old);
+       pid = fork();
+       if(pid == 0){
+               _clearuproc();
+               _p9uproc(0);
+       }
+       sigprocmask(SIG_SETMASK, &old, nil);
+       return pid;
+}
diff --git a/src/lib9/getenv.c b/src/lib9/getenv.c
new file mode 100644 (file)
index 0000000..9d805b5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+Plan 9 from User Space src/lib9/getenv.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/getenv.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+char*
+p9getenv(char *s)
+{
+       char *t;
+
+       t = getenv(s);
+       if(t == 0)
+               return 0;
+       return strdup(t);
+}
+
+int
+p9putenv(char *s, char *v)
+{
+       char *t;
+
+       t = smprint("%s=%s", s, v);
+       if(t == nil)
+               return -1;
+       putenv(t);
+       return 0;
+}
diff --git a/src/lib9/getfields.c b/src/lib9/getfields.c
new file mode 100644 (file)
index 0000000..898328c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+Inferno libkern/getfields.c
+http://code.google.com/p/inferno-os/source/browse/libkern/getfields.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <lib9.h>
+
+int
+getfields(char *str, char **args, int max, int mflag, char *set)
+{
+       Rune r;
+       int nr, intok, narg;
+
+       if(max <= 0)
+               return 0;
+
+       narg = 0;
+       args[narg] = str;
+       if(!mflag)
+               narg++;
+       intok = 0;
+       for(;; str += nr) {
+               nr = chartorune(&r, str);
+               if(r == 0)
+                       break;
+               if(utfrune(set, r)) {
+                       if(narg >= max)
+                               break;
+                       *str = 0;
+                       intok = 0;
+                       args[narg] = str + nr;
+                       if(!mflag)
+                               narg++;
+               } else {
+                       if(!intok && mflag)
+                               narg++;
+                       intok = 1;
+               }
+       }
+       return narg;
+}
diff --git a/src/lib9/getuser.c b/src/lib9/getuser.c
new file mode 100644 (file)
index 0000000..f70b35c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+Plan 9 from User Space src/lib9/getuser.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/getuser.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <pwd.h>
+#include <libc.h>
+
+char*
+getuser(void)
+{
+       static char user[64];
+       struct passwd *pw;
+
+       pw = getpwuid(getuid());
+       if(pw == nil)
+               return "none";
+       strecpy(user, user+sizeof user, pw->pw_name);
+       return user;
+}
diff --git a/src/lib9/getwd.c b/src/lib9/getwd.c
new file mode 100644 (file)
index 0000000..c3dd2b5
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Plan 9 from User Space src/lib9/getwd.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/getwd.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#include <libc.h>
+
+#undef getwd
+
+char*
+p9getwd(char *s, int ns)
+{
+       return getcwd(s, ns);
+}
diff --git a/src/lib9/jmp.c b/src/lib9/jmp.c
new file mode 100644 (file)
index 0000000..a606fb0
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Plan 9 from User Space src/lib9/jmp.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/jmp.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+void
+p9longjmp(p9jmp_buf buf, int val)
+{
+       siglongjmp((void*)buf, val);
+}
+
+void
+p9notejmp(void *x, p9jmp_buf buf, int val)
+{
+       USED(x);
+       siglongjmp((void*)buf, val);
+}
+
diff --git a/src/lib9/main.c b/src/lib9/main.c
new file mode 100644 (file)
index 0000000..45f86c7
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+Plan 9 from User Space src/lib9/main.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/main.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+extern void p9main(int, char**);
+
+int
+main(int argc, char **argv)
+{
+       p9main(argc, argv);
+       exits("main");
+       return 99;
+}
diff --git a/src/lib9/nan.c b/src/lib9/nan.c
new file mode 100644 (file)
index 0000000..e799432
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+Plan 9 from User Space src/lib9/nan.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/nan.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+#include "fmt/nan.h"
+
+double
+NaN(void)
+{
+       return __NaN();
+}
+
+double
+Inf(int sign)
+{
+       return __Inf(sign);
+}
+
+int
+isNaN(double x)
+{
+       return __isNaN(x);
+}
+
+int
+isInf(double x, int sign)
+{
+       return __isInf(x, sign);
+}
diff --git a/src/lib9/notify.c b/src/lib9/notify.c
new file mode 100644 (file)
index 0000000..84999b8
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+Plan 9 from User Space src/lib9/notify.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/notify.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/*
+ * Signal handling for Plan 9 programs.
+ * We stubbornly use the strings from Plan 9 instead
+ * of the enumerated Unix constants.
+ * There are some weird translations.  In particular,
+ * a "kill" note is the same as SIGTERM in Unix.
+ * There is no equivalent note to Unix's SIGKILL, since
+ * it's not a deliverable signal anyway.
+ *
+ * We do not handle SIGABRT or SIGSEGV, mainly because
+ * the thread library queues its notes for later, and we want
+ * to dump core with the state at time of delivery.
+ *
+ * We have to add some extra entry points to provide the
+ * ability to tweak which signals are deliverable and which
+ * are acted upon.  Notifydisable and notifyenable play with
+ * the process signal mask.  Notifyignore enables the signal
+ * but will not call notifyf when it comes in.  This is occasionally
+ * useful.
+ */
+
+#include <u.h>
+#include <signal.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+extern char *_p9sigstr(int, char*);
+extern int _p9strsig(char*);
+
+typedef struct Sig Sig;
+struct Sig
+{
+       int sig;                        /* signal number */
+       int flags;
+};
+
+enum
+{
+       Restart = 1<<0,
+       Ignore = 1<<1
+};
+
+static Sig sigs[] = {
+       SIGHUP,         0,
+       SIGINT,         0,
+       SIGQUIT,                0,
+       SIGILL,         0,
+       SIGTRAP,                0,
+/*     SIGABRT,                0,      */
+#ifdef SIGEMT
+       SIGEMT,         0,
+#endif
+       SIGFPE,         0,
+       SIGBUS,         0,
+/*     SIGSEGV,                0,      */
+       SIGCHLD,                Restart|Ignore,
+       SIGSYS,         0,
+       SIGPIPE,                Ignore,
+       SIGALRM,                0,
+       SIGTERM,                0,
+       SIGTSTP,                Restart|Ignore,
+/*     SIGTTIN,                Restart|Ignore, */
+/*     SIGTTOU,                Restart|Ignore, */
+       SIGXCPU,                0,
+       SIGXFSZ,                0,
+       SIGVTALRM,      0,
+       SIGUSR1,                0,
+       SIGUSR2,                0,
+#ifdef SIGWINCH
+       SIGWINCH,       Restart|Ignore,
+#endif
+#ifdef SIGINFO
+       SIGINFO,                Restart|Ignore,
+#endif
+};
+
+static Sig*
+findsig(int s)
+{
+       int i;
+
+       for(i=0; i<nelem(sigs); i++)
+               if(sigs[i].sig == s)
+                       return &sigs[i];
+       return nil;
+}
+
+/*
+ * The thread library initializes _notejmpbuf to its own
+ * routine which provides a per-pthread jump buffer.
+ * If we're not using the thread library, we assume we are
+ * single-threaded.
+ */
+typedef struct Jmp Jmp;
+struct Jmp
+{
+       p9jmp_buf b;
+};
+
+static Jmp onejmp;
+
+static Jmp*
+getonejmp(void)
+{
+       return &onejmp;
+}
+
+Jmp *(*_notejmpbuf)(void) = getonejmp;
+static void noteinit(void);
+
+/*
+ * Actual signal handler.
+ */
+
+static void (*notifyf)(void*, char*);  /* Plan 9 handler */
+
+static void
+signotify(int sig)
+{
+       char tmp[64];
+       Jmp *j;
+       Sig *s;
+
+       j = (*_notejmpbuf)();
+       switch(p9setjmp(j->b)){
+       case 0:
+               if(notifyf)
+                       (*notifyf)(nil, _p9sigstr(sig, tmp));
+               /* fall through */
+       case 1: /* noted(NDFLT) */
+               if(0)print("DEFAULT %d\n", sig);
+               s = findsig(sig);
+               if(s && (s->flags&Ignore))
+                       return;
+               signal(sig, SIG_DFL);
+               raise(sig);
+               _exit(1);
+       case 2: /* noted(NCONT) */
+               if(0)print("HANDLED %d\n", sig);
+               return;
+       }
+}
+
+static void
+signonotify(int sig)
+{
+       USED(sig);
+}
+
+int
+noted(int v)
+{
+       p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1);
+       abort();
+       return 0;
+}
+
+int
+notify(void (*f)(void*, char*))
+{
+       static int init;
+
+       notifyf = f;
+       if(!init){
+               init = 1;
+               noteinit();
+       }
+       return 0;
+}
+
+/*
+ * Nonsense about enabling and disabling signals.
+ */
+typedef void Sighandler(int);
+static Sighandler*
+handler(int s)
+{
+       struct sigaction sa;
+
+       sigaction(s, nil, &sa);
+       return sa.sa_handler;
+}
+
+static int
+notesetenable(int sig, int enabled)
+{
+       sigset_t mask, omask;
+
+       if(sig == 0)
+               return -1;
+
+       sigemptyset(&mask);
+       sigaddset(&mask, sig);
+       sigprocmask(enabled ? SIG_UNBLOCK : SIG_BLOCK, &mask, &omask);
+       return !sigismember(&omask, sig);
+}
+
+int
+noteenable(char *msg)
+{
+       return notesetenable(_p9strsig(msg), 1);
+}
+
+int
+notedisable(char *msg)
+{
+       return notesetenable(_p9strsig(msg), 0);
+}
+
+static int
+notifyseton(int s, int on)
+{
+       Sig *sig;
+       struct sigaction sa, osa;
+
+       sig = findsig(s);
+       if(sig == nil)
+               return -1;
+       memset(&sa, 0, sizeof sa);
+       sa.sa_handler = on ? signotify : signonotify;
+       if(sig->flags&Restart)
+               sa.sa_flags |= SA_RESTART;
+
+       /*
+        * We can't allow signals within signals because there's
+        * only one jump buffer.
+        */
+       sigfillset(&sa.sa_mask);
+
+       /*
+        * Install handler.
+        */
+       sigaction(sig->sig, &sa, &osa);
+       return osa.sa_handler == signotify;
+}
+
+int
+notifyon(char *msg)
+{
+       return notifyseton(_p9strsig(msg), 1);
+}
+
+int
+notifyoff(char *msg)
+{
+       return notifyseton(_p9strsig(msg), 0);
+}
+
+/*
+ * Initialization follows sigs table.
+ */
+static void
+noteinit(void)
+{
+       int i;
+       Sig *sig;
+
+       for(i=0; i<nelem(sigs); i++){
+               sig = &sigs[i];
+               /*
+                * If someone has already installed a handler,
+                * It's probably some ld preload nonsense,
+                * like pct (a SIGVTALRM-based profiler).
+                * Or maybe someone has already called notifyon/notifyoff.
+                * Leave it alone.
+                */
+               if(handler(sig->sig) != SIG_DFL)
+                       continue;
+               notifyseton(sig->sig, 1);
+       }
+}
+
diff --git a/src/lib9/nulldir.c b/src/lib9/nulldir.c
new file mode 100644 (file)
index 0000000..aa1a123
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+Inferno lib9/nulldir.c
+http://code.google.com/p/inferno-os/source/browse/lib9/nulldir.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+void
+nulldir(Dir *d)
+{
+       memset(d, ~0, sizeof(Dir));
+       d->name = d->uid = d->gid = d->muid = "";
+}
diff --git a/src/lib9/open.c b/src/lib9/open.c
new file mode 100644 (file)
index 0000000..1fa3c1b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+Plan 9 from User Space src/lib9/open.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/open.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#define _GNU_SOURCE    /* for Linux O_DIRECT */
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <sys/file.h>
+#include <libc.h>
+#ifndef O_DIRECT
+#define O_DIRECT 0
+#endif
+
+int
+p9open(char *name, int mode)
+{
+       int cexec, rclose;
+       int fd, umode, lock, rdwr;
+       struct flock fl;
+
+       rdwr = mode&3;
+       umode = rdwr;
+       cexec = mode&OCEXEC;
+       rclose = mode&ORCLOSE;
+       lock = mode&OLOCK;
+       mode &= ~(3|OCEXEC|ORCLOSE|OLOCK);
+       if(mode&OTRUNC){
+               umode |= O_TRUNC;
+               mode ^= OTRUNC;
+       }
+       if(mode&ODIRECT){
+               umode |= O_DIRECT;
+               mode ^= ODIRECT;
+       }
+       if(mode&ONONBLOCK){
+               umode |= O_NONBLOCK;
+               mode ^= ONONBLOCK;
+       }
+       if(mode&OAPPEND){
+               umode |= O_APPEND;
+               mode ^= OAPPEND;
+       }
+       if(mode){
+               werrstr("mode 0x%x not supported", mode);
+               return -1;
+       }
+       fd = open(name, umode);
+       if(fd >= 0){
+               if(lock){
+                       fl.l_type = (rdwr==OREAD) ? F_RDLCK : F_WRLCK;
+                       fl.l_whence = SEEK_SET;
+                       fl.l_start = 0;
+                       fl.l_len = 0;
+                       if(fcntl(fd, F_SETLK, &fl) < 0){
+                               close(fd);
+                               werrstr("lock: %r");
+                               return -1;
+                       }
+               }
+               if(cexec)
+                       fcntl(fd, F_SETFL, FD_CLOEXEC);
+               if(rclose)
+                       remove(name);
+       }
+       return fd;
+}
diff --git a/src/lib9/pipe.c b/src/lib9/pipe.c
new file mode 100644 (file)
index 0000000..0a7d073
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+Plan 9 from User Space src/lib9/getenv.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/getenv.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <u.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+#include <sys/socket.h>
+
+/*
+ * We use socketpair to get a two-way pipe.
+ * The pipe still doesn't preserve message boundaries.
+ * Worse, it cannot be reopened via /dev/fd/NNN on Linux.
+ */
+int
+p9pipe(int fd[2])
+{
+       return socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
+}
diff --git a/src/lib9/readn.c b/src/lib9/readn.c
new file mode 100644 (file)
index 0000000..76e497d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+Inferno lib9/readn.c
+http://code.google.com/p/inferno-os/source/browse/lib9/readn.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <lib9.h>
+
+long
+readn(int f, void *av, long n)
+{
+       char *a;
+       long m, t;
+
+       a = av;
+       t = 0;
+       while(t < n){
+               m = read(f, a+t, n-t);
+               if(m <= 0){
+                       if(t == 0)
+                               return m;
+                       break;
+               }
+               t += m;
+       }
+       return t;
+}
diff --git a/src/lib9/rfork.c b/src/lib9/rfork.c
new file mode 100644 (file)
index 0000000..c9d6321
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+Plan 9 from User Space src/lib9/rfork.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/rfork.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <libc.h>
+#undef rfork
+
+static void
+nop(int x)
+{
+       USED(x);
+}
+
+int
+p9rfork(int flags)
+{
+       int pid, status;
+       int p[2];
+       int n;
+       char buf[128], *q;
+       extern char **environ;
+
+       if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){
+               /* check other flags before we commit */
+               flags &= ~(RFPROC|RFFDG|RFENVG);
+               n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT|RFCENVG));
+               if(n){
+                       werrstr("unknown flags %08ux in rfork", n);
+                       return -1;
+               }
+               if(flags&RFNOWAIT){
+                       /*
+                        * BUG - should put the signal handler back after we
+                        * finish, but I just don't care.  If a program calls with
+                        * NOWAIT once, they're not likely to want child notes
+                        * after that.
+                        */
+                       signal(SIGCHLD, nop);
+                       if(pipe(p) < 0)
+                               return -1;
+               }
+               pid = fork();
+               if(pid == -1)
+                       return -1;
+               if(flags&RFNOWAIT){
+                       flags &= ~RFNOWAIT;
+                       if(pid){
+                               /*
+                                * Parent - wait for child to fork wait-free child.
+                                * Then read pid from pipe.  Assume pipe buffer can absorb the write.
+                                */
+                               close(p[1]);
+                               status = 0;
+                               if(wait4(pid, &status, 0, 0) < 0){
+                                       werrstr("pipe dance - wait4 - %r");
+                                       close(p[0]);
+                                       return -1;
+                               }
+                               n = readn(p[0], buf, sizeof buf-1);
+                               close(p[0]);
+                               if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){
+                                       if(!WIFEXITED(status))
+                                               werrstr("pipe dance - !exited 0x%ux", status);
+                                       else if(WEXITSTATUS(status) != 0)
+                                               werrstr("pipe dance - non-zero status 0x%ux", status);
+                                       else if(n < 0)
+                                               werrstr("pipe dance - pipe read error - %r");
+                                       else if(n == 0)
+                                               werrstr("pipe dance - pipe read eof");
+                                       else
+                                               werrstr("pipe dance - unknown failure");
+                                       return -1;
+                               }
+                               buf[n] = 0;
+                               if(buf[0] == 'x'){
+                                       werrstr("%s", buf+2);
+                                       return -1;
+                               }
+                               pid = strtol(buf, &q, 0);
+                       }else{
+                               /*
+                                * Child - fork a new child whose wait message can't
+                                * get back to the parent because we're going to exit!
+                                */
+                               signal(SIGCHLD, SIG_IGN);
+                               close(p[0]);
+                               pid = fork();
+                               if(pid){
+                                       /* Child parent - send status over pipe and exit. */
+                                       if(pid > 0)
+                                               fprint(p[1], "%d", pid);
+                                       else
+                                               fprint(p[1], "x %r");
+                                       close(p[1]);
+                                       _exit(0);
+                               }else{
+                                       /* Child child - close pipe. */
+                                       close(p[1]);
+                               }
+                       }
+               }
+               if(pid != 0)
+                       return pid;
+               if(flags&RFCENVG)
+                       if(environ)
+                               *environ = nil;
+       }
+       if(flags&RFPROC){
+               werrstr("cannot use rfork for shared memory -- use libthread");
+               return -1;
+       }
+       if(flags&RFNAMEG){
+               /* XXX set $NAMESPACE to a new directory */
+               flags &= ~RFNAMEG;
+       }
+       if(flags&RFNOTEG){
+               setpgid(0, getpid());
+               flags &= ~RFNOTEG;
+       }
+       if(flags&RFNOWAIT){
+               werrstr("cannot use RFNOWAIT without RFPROC");
+               return -1;
+       }
+       if(flags){
+               werrstr("unknown flags %08ux in rfork", flags);
+               return -1;
+       }
+       return 0;
+}
diff --git a/src/lib9/seek.c b/src/lib9/seek.c
new file mode 100644 (file)
index 0000000..9170038
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Plan 9 from User Space src/lib9/seek.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/seek.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+vlong
+seek(int fd, vlong offset, int whence)
+{
+       return lseek(fd, offset, whence);
+}
diff --git a/src/lib9/strecpy.c b/src/lib9/strecpy.c
new file mode 100644 (file)
index 0000000..f38b524
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Inferno lib9/strecpy.c
+http://code.google.com/p/inferno-os/source/browse/lib9/strecpy.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <lib9.h>
+
+char*
+strecpy(char *to, char *e, char *from)
+{
+       if(to >= e)
+               return to;
+       to = memccpy(to, from, '\0', e - to);
+       if(to == nil){
+               to = e - 1;
+               *to = '\0';
+       }else{
+               to--;
+       }
+       return to;
+}
diff --git a/src/lib9/sysfatal.c b/src/lib9/sysfatal.c
new file mode 100644 (file)
index 0000000..a5af3e1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+Plan 9 from User Space src/lib9/sysfatal.c
+http://code.swtch.com/plan9port/src/tip/src/lib9/sysfatal.c
+
+Copyright 2001-2007 Russ Cox.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <u.h>
+#include <libc.h>
+
+void (*_sysfatal)(char*, ...);
+
+void
+sysfatal(char *fmt, ...)
+{
+       char buf[256];
+       va_list arg;
+
+       va_start(arg, fmt);
+       if(_sysfatal)
+               (*_sysfatal)(fmt, arg);
+       vseprint(buf, buf+sizeof buf, fmt, arg);
+       va_end(arg);
+
+       __fixargv0();
+       fprint(2, "%s: %s\n", argv0 ? argv0 : "<prog>", buf);
+       exits("fatal");
+}
+
diff --git a/src/lib9/tokenize.c b/src/lib9/tokenize.c
new file mode 100644 (file)
index 0000000..6b8c0e7
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+Inferno lib9/tokenize.c
+http://code.google.com/p/inferno-os/source/browse/lib9/tokenize.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <lib9.h>
+
+static char qsep[] = " \t\r\n";
+
+static char*
+qtoken(char *s, char *sep)
+{
+       int quoting;
+       char *t;
+
+       quoting = 0;
+       t = s;  /* s is output string, t is input string */
+       while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){
+               if(*t != '\''){
+                       *s++ = *t++;
+                       continue;
+               }
+               /* *t is a quote */
+               if(!quoting){
+                       quoting = 1;
+                       t++;
+                       continue;
+               }
+               /* quoting and we're on a quote */
+               if(t[1] != '\''){
+                       /* end of quoted section; absorb closing quote */
+                       t++;
+                       quoting = 0;
+                       continue;
+               }
+               /* doubled quote; fold one quote into two */
+               t++;
+               *s++ = *t++;
+       }
+       if(*s != '\0'){
+               *s = '\0';
+               if(t == s)
+                       t++;
+       }
+       return t;
+}
+
+static char*
+etoken(char *t, char *sep)
+{
+       int quoting;
+
+       /* move to end of next token */
+       quoting = 0;
+       while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){
+               if(*t != '\''){
+                       t++;
+                       continue;
+               }
+               /* *t is a quote */
+               if(!quoting){
+                       quoting = 1;
+                       t++;
+                       continue;
+               }
+               /* quoting and we're on a quote */
+               if(t[1] != '\''){
+                       /* end of quoted section; absorb closing quote */
+                       t++;
+                       quoting = 0;
+                       continue;
+               }
+               /* doubled quote; fold one quote into two */
+               t += 2;
+       }
+       return t;
+}
+
+int
+gettokens(char *s, char **args, int maxargs, char *sep)
+{
+       int nargs;
+
+       for(nargs=0; nargs<maxargs; nargs++){
+               while(*s!='\0' && utfrune(sep, *s)!=nil)
+                       *s++ = '\0';
+               if(*s == '\0')
+                       break;
+               args[nargs] = s;
+               s = etoken(s, sep);
+       }
+
+       return nargs;
+}
+
+int
+tokenize(char *s, char **args, int maxargs)
+{
+       int nargs;
+
+       for(nargs=0; nargs<maxargs; nargs++){
+               while(*s!='\0' && utfrune(qsep, *s)!=nil)
+                       s++;
+               if(*s == '\0')
+                       break;
+               args[nargs] = s;
+               s = qtoken(s, qsep);
+       }
+
+       return nargs;
+}
diff --git a/src/lib9/utf/rune.c b/src/lib9/utf/rune.c
new file mode 100644 (file)
index 0000000..3d6831b
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+enum
+{
+       Bit1    = 7,
+       Bitx    = 6,
+       Bit2    = 5,
+       Bit3    = 4,
+       Bit4    = 3,
+
+       T1      = ((1<<(Bit1+1))-1) ^ 0xFF,     /* 0000 0000 */
+       Tx      = ((1<<(Bitx+1))-1) ^ 0xFF,     /* 1000 0000 */
+       T2      = ((1<<(Bit2+1))-1) ^ 0xFF,     /* 1100 0000 */
+       T3      = ((1<<(Bit3+1))-1) ^ 0xFF,     /* 1110 0000 */
+       T4      = ((1<<(Bit4+1))-1) ^ 0xFF,     /* 1111 0000 */
+
+       Rune1   = (1<<(Bit1+0*Bitx))-1,         /* 0000 0000 0111 1111 */
+       Rune2   = (1<<(Bit2+1*Bitx))-1,         /* 0000 0111 1111 1111 */
+       Rune3   = (1<<(Bit3+2*Bitx))-1,         /* 1111 1111 1111 1111 */
+
+       Maskx   = (1<<Bitx)-1,                  /* 0011 1111 */
+       Testx   = Maskx ^ 0xFF,                 /* 1100 0000 */
+
+       Bad     = Runeerror
+};
+
+int
+chartorune(Rune *rune, char *str)
+{
+       int c, c1, c2;
+       long l;
+
+       /*
+        * one character sequence
+        *      00000-0007F => T1
+        */
+       c = *(uchar*)str;
+       if(c < Tx) {
+               *rune = c;
+               return 1;
+       }
+
+       /*
+        * two character sequence
+        *      0080-07FF => T2 Tx
+        */
+       c1 = *(uchar*)(str+1) ^ Tx;
+       if(c1 & Testx)
+               goto bad;
+       if(c < T3) {
+               if(c < T2)
+                       goto bad;
+               l = ((c << Bitx) | c1) & Rune2;
+               if(l <= Rune1)
+                       goto bad;
+               *rune = l;
+               return 2;
+       }
+
+       /*
+        * three character sequence
+        *      0800-FFFF => T3 Tx Tx
+        */
+       c2 = *(uchar*)(str+2) ^ Tx;
+       if(c2 & Testx)
+               goto bad;
+       if(c < T4) {
+               l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
+               if(l <= Rune2)
+                       goto bad;
+               *rune = l;
+               return 3;
+       }
+
+       /*
+        * bad decoding
+        */
+bad:
+       *rune = Bad;
+       return 1;
+}
+
+int
+runetochar(char *str, Rune *rune)
+{
+       long c;
+
+       /*
+        * one character sequence
+        *      00000-0007F => 00-7F
+        */
+       c = *rune;
+       if(c <= Rune1) {
+               str[0] = c;
+               return 1;
+       }
+
+       /*
+        * two character sequence
+        *      0080-07FF => T2 Tx
+        */
+       if(c <= Rune2) {
+               str[0] = T2 | (c >> 1*Bitx);
+               str[1] = Tx | (c & Maskx);
+               return 2;
+       }
+
+       /*
+        * three character sequence
+        *      0800-FFFF => T3 Tx Tx
+        */
+       str[0] = T3 |  (c >> 2*Bitx);
+       str[1] = Tx | ((c >> 1*Bitx) & Maskx);
+       str[2] = Tx |  (c & Maskx);
+       return 3;
+}
+
+int
+runelen(long c)
+{
+       Rune rune;
+       char str[10];
+
+       rune = c;
+       return runetochar(str, &rune);
+}
+
+int
+runenlen(Rune *r, int nrune)
+{
+       int nb, c;
+
+       nb = 0;
+       while(nrune--) {
+               c = *r++;
+               if(c <= Rune1)
+                       nb++;
+               else
+               if(c <= Rune2)
+                       nb += 2;
+               else
+                       nb += 3;
+       }
+       return nb;
+}
+
+int
+fullrune(char *str, int n)
+{
+       int c;
+
+       if(n > 0) {
+               c = *(uchar*)str;
+               if(c < Tx)
+                       return 1;
+               if(n > 1)
+                       if(c < T3 || n > 2)
+                               return 1;
+       }
+       return 0;
+}
diff --git a/src/lib9/utf/runetype.c b/src/lib9/utf/runetype.c
new file mode 100644 (file)
index 0000000..ac6d7b5
--- /dev/null
@@ -0,0 +1,1151 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+/*
+ * alpha ranges -
+ *     only covers ranges not in lower||upper
+ */
+static
+Rune   __alpha2[] =
+{
+       0x00d8, 0x00f6, /* Ø - ö */
+       0x00f8, 0x01f5, /* ø - ǵ */
+       0x0250, 0x02a8, /* ɐ - ʨ */
+       0x038e, 0x03a1, /* Ύ - Ρ */
+       0x03a3, 0x03ce, /* Σ - ώ */
+       0x03d0, 0x03d6, /* ϐ - ϖ */
+       0x03e2, 0x03f3, /* Ϣ - ϳ */
+       0x0490, 0x04c4, /* Ґ - ӄ */
+       0x0561, 0x0587, /* ա - և */
+       0x05d0, 0x05ea, /* א - ת */
+       0x05f0, 0x05f2, /* װ - ײ */
+       0x0621, 0x063a, /* ء - غ */
+       0x0640, 0x064a, /* ـ - ي */
+       0x0671, 0x06b7, /* ٱ - ڷ */
+       0x06ba, 0x06be, /* ں - ھ */
+       0x06c0, 0x06ce, /* ۀ - ێ */
+       0x06d0, 0x06d3, /* ې - ۓ */
+       0x0905, 0x0939, /* अ - ह */
+       0x0958, 0x0961, /* क़ - ॡ */
+       0x0985, 0x098c, /* অ - ঌ */
+       0x098f, 0x0990, /* এ - ঐ */
+       0x0993, 0x09a8, /* ও - ন */
+       0x09aa, 0x09b0, /* প - র */
+       0x09b6, 0x09b9, /* শ - হ */
+       0x09dc, 0x09dd, /* ড় - ঢ় */
+       0x09df, 0x09e1, /* য় - ৡ */
+       0x09f0, 0x09f1, /* ৰ - ৱ */
+       0x0a05, 0x0a0a, /* ਅ - ਊ */
+       0x0a0f, 0x0a10, /* ਏ - ਐ */
+       0x0a13, 0x0a28, /* ਓ - ਨ */
+       0x0a2a, 0x0a30, /* ਪ - ਰ */
+       0x0a32, 0x0a33, /* ਲ - ਲ਼ */
+       0x0a35, 0x0a36, /* ਵ - ਸ਼ */
+       0x0a38, 0x0a39, /* ਸ - ਹ */
+       0x0a59, 0x0a5c, /* ਖ਼ - ੜ */
+       0x0a85, 0x0a8b, /* અ - ઋ */
+       0x0a8f, 0x0a91, /* એ - ઑ */
+       0x0a93, 0x0aa8, /* ઓ - ન */
+       0x0aaa, 0x0ab0, /* પ - ર */
+       0x0ab2, 0x0ab3, /* લ - ળ */
+       0x0ab5, 0x0ab9, /* વ - હ */
+       0x0b05, 0x0b0c, /* ଅ - ଌ */
+       0x0b0f, 0x0b10, /* ଏ - ଐ */
+       0x0b13, 0x0b28, /* ଓ - ନ */
+       0x0b2a, 0x0b30, /* ପ - ର */
+       0x0b32, 0x0b33, /* ଲ - ଳ */
+       0x0b36, 0x0b39, /* ଶ - ହ */
+       0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */
+       0x0b5f, 0x0b61, /* ୟ - ୡ */
+       0x0b85, 0x0b8a, /* அ - ஊ */
+       0x0b8e, 0x0b90, /* எ - ஐ */
+       0x0b92, 0x0b95, /* ஒ - க */
+       0x0b99, 0x0b9a, /* ங - ச */
+       0x0b9e, 0x0b9f, /* ஞ - ட */
+       0x0ba3, 0x0ba4, /* ண - த */
+       0x0ba8, 0x0baa, /* ந - ப */
+       0x0bae, 0x0bb5, /* ம - வ */
+       0x0bb7, 0x0bb9, /* ஷ - ஹ */
+       0x0c05, 0x0c0c, /* అ - ఌ */
+       0x0c0e, 0x0c10, /* ఎ - ఐ */
+       0x0c12, 0x0c28, /* ఒ - న */
+       0x0c2a, 0x0c33, /* ప - ళ */
+       0x0c35, 0x0c39, /* వ - హ */
+       0x0c60, 0x0c61, /* ౠ - ౡ */
+       0x0c85, 0x0c8c, /* ಅ - ಌ */
+       0x0c8e, 0x0c90, /* ಎ - ಐ */
+       0x0c92, 0x0ca8, /* ಒ - ನ */
+       0x0caa, 0x0cb3, /* ಪ - ಳ */
+       0x0cb5, 0x0cb9, /* ವ - ಹ */
+       0x0ce0, 0x0ce1, /* ೠ - ೡ */
+       0x0d05, 0x0d0c, /* അ - ഌ */
+       0x0d0e, 0x0d10, /* എ - ഐ */
+       0x0d12, 0x0d28, /* ഒ - ന */
+       0x0d2a, 0x0d39, /* പ - ഹ */
+       0x0d60, 0x0d61, /* ൠ - ൡ */
+       0x0e01, 0x0e30, /* ก - ะ */
+       0x0e32, 0x0e33, /* า - ำ */
+       0x0e40, 0x0e46, /* เ - ๆ */
+       0x0e5a, 0x0e5b, /* ๚ - ๛ */
+       0x0e81, 0x0e82, /* ກ - ຂ */
+       0x0e87, 0x0e88, /* ງ - ຈ */
+       0x0e94, 0x0e97, /* ດ - ທ */
+       0x0e99, 0x0e9f, /* ນ - ຟ */
+       0x0ea1, 0x0ea3, /* ມ - ຣ */
+       0x0eaa, 0x0eab, /* ສ - ຫ */
+       0x0ead, 0x0eae, /* ອ - ຮ */
+       0x0eb2, 0x0eb3, /* າ - ຳ */
+       0x0ec0, 0x0ec4, /* ເ - ໄ */
+       0x0edc, 0x0edd, /* ໜ - ໝ */
+       0x0f18, 0x0f19, /* ༘ - ༙ */
+       0x0f40, 0x0f47, /* ཀ - ཇ */
+       0x0f49, 0x0f69, /* ཉ - ཀྵ */
+       0x10d0, 0x10f6, /* ა - ჶ */
+       0x1100, 0x1159, /* ᄀ - ᅙ */
+       0x115f, 0x11a2, /* ᅟ - ᆢ */
+       0x11a8, 0x11f9, /* ᆨ - ᇹ */
+       0x1e00, 0x1e9b, /* Ḁ - ẛ */
+       0x1f50, 0x1f57, /* ὐ - ὗ */
+       0x1f80, 0x1fb4, /* ᾀ - ᾴ */
+       0x1fb6, 0x1fbc, /* ᾶ - ᾼ */
+       0x1fc2, 0x1fc4, /* ῂ - ῄ */
+       0x1fc6, 0x1fcc, /* ῆ - ῌ */
+       0x1fd0, 0x1fd3, /* ῐ - ΐ */
+       0x1fd6, 0x1fdb, /* ῖ - Ί */
+       0x1fe0, 0x1fec, /* ῠ - Ῥ */
+       0x1ff2, 0x1ff4, /* ῲ - ῴ */
+       0x1ff6, 0x1ffc, /* ῶ - ῼ */
+       0x210a, 0x2113, /* ℊ - ℓ */
+       0x2115, 0x211d, /* ℕ - ℝ */
+       0x2120, 0x2122, /* ℠ - ™ */
+       0x212a, 0x2131, /* K - ℱ */
+       0x2133, 0x2138, /* ℳ - ℸ */
+       0x3041, 0x3094, /* ぁ - ゔ */
+       0x30a1, 0x30fa, /* ァ - ヺ */
+       0x3105, 0x312c, /* ㄅ - ㄬ */
+       0x3131, 0x318e, /* ㄱ - ㆎ */
+       0x3192, 0x319f, /* ㆒ - ㆟ */
+       0x3260, 0x327b, /* ㉠ - ㉻ */
+       0x328a, 0x32b0, /* ㊊ - ㊰ */
+       0x32d0, 0x32fe, /* ㋐ - ㋾ */
+       0x3300, 0x3357, /* ㌀ - ㍗ */
+       0x3371, 0x3376, /* ㍱ - ㍶ */
+       0x337b, 0x3394, /* ㍻ - ㎔ */
+       0x3399, 0x339e, /* ㎙ - ㎞ */
+       0x33a9, 0x33ad, /* ㎩ - ㎭ */
+       0x33b0, 0x33c1, /* ㎰ - ㏁ */
+       0x33c3, 0x33c5, /* ㏃ - ㏅ */
+       0x33c7, 0x33d7, /* ㏇ - ㏗ */
+       0x33d9, 0x33dd, /* ㏙ - ㏝ */
+       0x4e00, 0x9fff, /* 一 - 鿿 */
+       0xac00, 0xd7a3, /* 가 - 힣 */
+       0xf900, 0xfb06, /* 豈 - st */
+       0xfb13, 0xfb17, /* ﬓ - ﬗ */
+       0xfb1f, 0xfb28, /* ײַ - ﬨ */
+       0xfb2a, 0xfb36, /* שׁ - זּ */
+       0xfb38, 0xfb3c, /* טּ - לּ */
+       0xfb40, 0xfb41, /* נּ - סּ */
+       0xfb43, 0xfb44, /* ףּ - פּ */
+       0xfb46, 0xfbb1, /* צּ - ﮱ */
+       0xfbd3, 0xfd3d, /* ﯓ - ﴽ */
+       0xfd50, 0xfd8f, /* ﵐ - ﶏ */
+       0xfd92, 0xfdc7, /* ﶒ - ﷇ */
+       0xfdf0, 0xfdf9, /* ﷰ - ﷹ */
+       0xfe70, 0xfe72, /* ﹰ - ﹲ */
+       0xfe76, 0xfefc, /* ﹶ - ﻼ */
+       0xff66, 0xff6f, /* ヲ - ッ */
+       0xff71, 0xff9d, /* ア - ン */
+       0xffa0, 0xffbe, /* ᅠ - ᄒ */
+       0xffc2, 0xffc7, /* ᅡ - ᅦ */
+       0xffca, 0xffcf, /* ᅧ - ᅬ */
+       0xffd2, 0xffd7, /* ᅭ - ᅲ */
+       0xffda, 0xffdc, /* ᅳ - ᅵ */
+};
+
+/*
+ * alpha singlets -
+ *     only covers ranges not in lower||upper
+ */
+static
+Rune   __alpha1[] =
+{
+       0x00aa, /* ª */
+       0x00b5, /* µ */
+       0x00ba, /* º */
+       0x03da, /* Ϛ */
+       0x03dc, /* Ϝ */
+       0x03de, /* Ϟ */
+       0x03e0, /* Ϡ */
+       0x06d5, /* ە */
+       0x09b2, /* ল */
+       0x0a5e, /* ਫ਼ */
+       0x0a8d, /* ઍ */
+       0x0ae0, /* ૠ */
+       0x0b9c, /* ஜ */
+       0x0cde, /* ೞ */
+       0x0e4f, /* ๏ */
+       0x0e84, /* ຄ */
+       0x0e8a, /* ຊ */
+       0x0e8d, /* ຍ */
+       0x0ea5, /* ລ */
+       0x0ea7, /* ວ */
+       0x0eb0, /* ະ */
+       0x0ebd, /* ຽ */
+       0x1fbe, /* ι */
+       0x207f, /* ⁿ */
+       0x20a8, /* ₨ */
+       0x2102, /* ℂ */
+       0x2107, /* ℇ */
+       0x2124, /* ℤ */
+       0x2126, /* Ω */
+       0x2128, /* ℨ */
+       0xfb3e, /* מּ */
+       0xfe74, /* ﹴ */
+};
+
+/*
+ * space ranges
+ */
+static
+Rune   __space2[] =
+{
+       0x0009, 0x000a, /* tab and newline */
+       0x0020, 0x0020, /* space */
+       0x00a0, 0x00a0, /*   */
+       0x2000, 0x200b, /*   - ​ */
+       0x2028, 0x2029, /* 
 - 
 */
+       0x3000, 0x3000, /*   */
+       0xfeff, 0xfeff, /*  */
+};
+
+/*
+ * lower case ranges
+ *     3rd col is conversion excess 500
+ */
+static
+Rune   __toupper2[] =
+{
+       0x0061, 0x007a, 468,    /* a-z A-Z */
+       0x00e0, 0x00f6, 468,    /* à-ö À-Ö */
+       0x00f8, 0x00fe, 468,    /* ø-þ Ø-Þ */
+       0x0256, 0x0257, 295,    /* ɖ-ɗ Ɖ-Ɗ */
+       0x0258, 0x0259, 298,    /* ɘ-ə Ǝ-Ə */
+       0x028a, 0x028b, 283,    /* ʊ-ʋ Ʊ-Ʋ */
+       0x03ad, 0x03af, 463,    /* έ-ί Έ-Ί */
+       0x03b1, 0x03c1, 468,    /* α-ρ Α-Ρ */
+       0x03c3, 0x03cb, 468,    /* σ-ϋ Σ-Ϋ */
+       0x03cd, 0x03ce, 437,    /* ύ-ώ Ύ-Ώ */
+       0x0430, 0x044f, 468,    /* а-я А-Я */
+       0x0451, 0x045c, 420,    /* ё-ќ Ё-Ќ */
+       0x045e, 0x045f, 420,    /* ў-џ Ў-Џ */
+       0x0561, 0x0586, 452,    /* ա-ֆ Ա-Ֆ */
+       0x1f00, 0x1f07, 508,    /* ἀ-ἇ Ἀ-Ἇ */
+       0x1f10, 0x1f15, 508,    /* ἐ-ἕ Ἐ-Ἕ */
+       0x1f20, 0x1f27, 508,    /* ἠ-ἧ Ἠ-Ἧ */
+       0x1f30, 0x1f37, 508,    /* ἰ-ἷ Ἰ-Ἷ */
+       0x1f40, 0x1f45, 508,    /* ὀ-ὅ Ὀ-Ὅ */
+       0x1f60, 0x1f67, 508,    /* ὠ-ὧ Ὠ-Ὧ */
+       0x1f70, 0x1f71, 574,    /* ὰ-ά Ὰ-Ά */
+       0x1f72, 0x1f75, 586,    /* ὲ-ή Ὲ-Ή */
+       0x1f76, 0x1f77, 600,    /* ὶ-ί Ὶ-Ί */
+       0x1f78, 0x1f79, 628,    /* ὸ-ό Ὸ-Ό */
+       0x1f7a, 0x1f7b, 612,    /* ὺ-ύ Ὺ-Ύ */
+       0x1f7c, 0x1f7d, 626,    /* ὼ-ώ Ὼ-Ώ */
+       0x1f80, 0x1f87, 508,    /* ᾀ-ᾇ ᾈ-ᾏ */
+       0x1f90, 0x1f97, 508,    /* ᾐ-ᾗ ᾘ-ᾟ */
+       0x1fa0, 0x1fa7, 508,    /* ᾠ-ᾧ ᾨ-ᾯ */
+       0x1fb0, 0x1fb1, 508,    /* ᾰ-ᾱ Ᾰ-Ᾱ */
+       0x1fd0, 0x1fd1, 508,    /* ῐ-ῑ Ῐ-Ῑ */
+       0x1fe0, 0x1fe1, 508,    /* ῠ-ῡ Ῠ-Ῡ */
+       0x2170, 0x217f, 484,    /* ⅰ-ⅿ Ⅰ-Ⅿ */
+       0x24d0, 0x24e9, 474,    /* ⓐ-ⓩ Ⓐ-Ⓩ */
+       0xff41, 0xff5a, 468,    /* a-z A-Z */
+};
+
+/*
+ * lower case singlets
+ *     2nd col is conversion excess 500
+ */
+static
+Rune   __toupper1[] =
+{
+       0x00ff, 621,    /* ÿ Ÿ */
+       0x0101, 499,    /* ā Ā */
+       0x0103, 499,    /* ă Ă */
+       0x0105, 499,    /* ą Ą */
+       0x0107, 499,    /* ć Ć */
+       0x0109, 499,    /* ĉ Ĉ */
+       0x010b, 499,    /* ċ Ċ */
+       0x010d, 499,    /* č Č */
+       0x010f, 499,    /* ď Ď */
+       0x0111, 499,    /* đ Đ */
+       0x0113, 499,    /* ē Ē */
+       0x0115, 499,    /* ĕ Ĕ */
+       0x0117, 499,    /* ė Ė */
+       0x0119, 499,    /* ę Ę */
+       0x011b, 499,    /* ě Ě */
+       0x011d, 499,    /* ĝ Ĝ */
+       0x011f, 499,    /* ğ Ğ */
+       0x0121, 499,    /* ġ Ġ */
+       0x0123, 499,    /* ģ Ģ */
+       0x0125, 499,    /* ĥ Ĥ */
+       0x0127, 499,    /* ħ Ħ */
+       0x0129, 499,    /* ĩ Ĩ */
+       0x012b, 499,    /* ī Ī */
+       0x012d, 499,    /* ĭ Ĭ */
+       0x012f, 499,    /* į Į */
+       0x0131, 268,    /* ı I */
+       0x0133, 499,    /* ij IJ */
+       0x0135, 499,    /* ĵ Ĵ */
+       0x0137, 499,    /* ķ Ķ */
+       0x013a, 499,    /* ĺ Ĺ */
+       0x013c, 499,    /* ļ Ļ */
+       0x013e, 499,    /* ľ Ľ */
+       0x0140, 499,    /* ŀ Ŀ */
+       0x0142, 499,    /* ł Ł */
+       0x0144, 499,    /* ń Ń */
+       0x0146, 499,    /* ņ Ņ */
+       0x0148, 499,    /* ň Ň */
+       0x014b, 499,    /* ŋ Ŋ */
+       0x014d, 499,    /* ō Ō */
+       0x014f, 499,    /* ŏ Ŏ */
+       0x0151, 499,    /* ő Ő */
+       0x0153, 499,    /* œ Œ */
+       0x0155, 499,    /* ŕ Ŕ */
+       0x0157, 499,    /* ŗ Ŗ */
+       0x0159, 499,    /* ř Ř */
+       0x015b, 499,    /* ś Ś */
+       0x015d, 499,    /* ŝ Ŝ */
+       0x015f, 499,    /* ş Ş */
+       0x0161, 499,    /* š Š */
+       0x0163, 499,    /* ţ Ţ */
+       0x0165, 499,    /* ť Ť */
+       0x0167, 499,    /* ŧ Ŧ */
+       0x0169, 499,    /* ũ Ũ */
+       0x016b, 499,    /* ū Ū */
+       0x016d, 499,    /* ŭ Ŭ */
+       0x016f, 499,    /* ů Ů */
+       0x0171, 499,    /* ű Ű */
+       0x0173, 499,    /* ų Ų */
+       0x0175, 499,    /* ŵ Ŵ */
+       0x0177, 499,    /* ŷ Ŷ */
+       0x017a, 499,    /* ź Ź */
+       0x017c, 499,    /* ż Ż */
+       0x017e, 499,    /* ž Ž */
+       0x017f, 200,    /* ſ S */
+       0x0183, 499,    /* ƃ Ƃ */
+       0x0185, 499,    /* ƅ Ƅ */
+       0x0188, 499,    /* ƈ Ƈ */
+       0x018c, 499,    /* ƌ Ƌ */
+       0x0192, 499,    /* ƒ Ƒ */
+       0x0199, 499,    /* ƙ Ƙ */
+       0x01a1, 499,    /* ơ Ơ */
+       0x01a3, 499,    /* ƣ Ƣ */
+       0x01a5, 499,    /* ƥ Ƥ */
+       0x01a8, 499,    /* ƨ Ƨ */
+       0x01ad, 499,    /* ƭ Ƭ */
+       0x01b0, 499,    /* ư Ư */
+       0x01b4, 499,    /* ƴ Ƴ */
+       0x01b6, 499,    /* ƶ Ƶ */
+       0x01b9, 499,    /* ƹ Ƹ */
+       0x01bd, 499,    /* ƽ Ƽ */
+       0x01c5, 499,    /* Dž DŽ */
+       0x01c6, 498,    /* dž DŽ */
+       0x01c8, 499,    /* Lj LJ */
+       0x01c9, 498,    /* lj LJ */
+       0x01cb, 499,    /* Nj NJ */
+       0x01cc, 498,    /* nj NJ */
+       0x01ce, 499,    /* ǎ Ǎ */
+       0x01d0, 499,    /* ǐ Ǐ */
+       0x01d2, 499,    /* ǒ Ǒ */
+       0x01d4, 499,    /* ǔ Ǔ */
+       0x01d6, 499,    /* ǖ Ǖ */
+       0x01d8, 499,    /* ǘ Ǘ */
+       0x01da, 499,    /* ǚ Ǚ */
+       0x01dc, 499,    /* ǜ Ǜ */
+       0x01df, 499,    /* ǟ Ǟ */
+       0x01e1, 499,    /* ǡ Ǡ */
+       0x01e3, 499,    /* ǣ Ǣ */
+       0x01e5, 499,    /* ǥ Ǥ */
+       0x01e7, 499,    /* ǧ Ǧ */
+       0x01e9, 499,    /* ǩ Ǩ */
+       0x01eb, 499,    /* ǫ Ǫ */
+       0x01ed, 499,    /* ǭ Ǭ */
+       0x01ef, 499,    /* ǯ Ǯ */
+       0x01f2, 499,    /* Dz DZ */
+       0x01f3, 498,    /* dz DZ */
+       0x01f5, 499,    /* ǵ Ǵ */
+       0x01fb, 499,    /* ǻ Ǻ */
+       0x01fd, 499,    /* ǽ Ǽ */
+       0x01ff, 499,    /* ǿ Ǿ */
+       0x0201, 499,    /* ȁ Ȁ */
+       0x0203, 499,    /* ȃ Ȃ */
+       0x0205, 499,    /* ȅ Ȅ */
+       0x0207, 499,    /* ȇ Ȇ */
+       0x0209, 499,    /* ȉ Ȉ */
+       0x020b, 499,    /* ȋ Ȋ */
+       0x020d, 499,    /* ȍ Ȍ */
+       0x020f, 499,    /* ȏ Ȏ */
+       0x0211, 499,    /* ȑ Ȑ */
+       0x0213, 499,    /* ȓ Ȓ */
+       0x0215, 499,    /* ȕ Ȕ */
+       0x0217, 499,    /* ȗ Ȗ */
+       0x0253, 290,    /* ɓ Ɓ */
+       0x0254, 294,    /* ɔ Ɔ */
+       0x025b, 297,    /* ɛ Ɛ */
+       0x0260, 295,    /* ɠ Ɠ */
+       0x0263, 293,    /* ɣ Ɣ */
+       0x0268, 291,    /* ɨ Ɨ */
+       0x0269, 289,    /* ɩ Ɩ */
+       0x026f, 289,    /* ɯ Ɯ */
+       0x0272, 287,    /* ɲ Ɲ */
+       0x0283, 282,    /* ʃ Ʃ */
+       0x0288, 282,    /* ʈ Ʈ */
+       0x0292, 281,    /* ʒ Ʒ */
+       0x03ac, 462,    /* ά Ά */
+       0x03cc, 436,    /* ό Ό */
+       0x03d0, 438,    /* ϐ Β */
+       0x03d1, 443,    /* ϑ Θ */
+       0x03d5, 453,    /* ϕ Φ */
+       0x03d6, 446,    /* ϖ Π */
+       0x03e3, 499,    /* ϣ Ϣ */
+       0x03e5, 499,    /* ϥ Ϥ */
+       0x03e7, 499,    /* ϧ Ϧ */
+       0x03e9, 499,    /* ϩ Ϩ */
+       0x03eb, 499,    /* ϫ Ϫ */
+       0x03ed, 499,    /* ϭ Ϭ */
+       0x03ef, 499,    /* ϯ Ϯ */
+       0x03f0, 414,    /* ϰ Κ */
+       0x03f1, 420,    /* ϱ Ρ */
+       0x0461, 499,    /* ѡ Ѡ */
+       0x0463, 499,    /* ѣ Ѣ */
+       0x0465, 499,    /* ѥ Ѥ */
+       0x0467, 499,    /* ѧ Ѧ */
+       0x0469, 499,    /* ѩ Ѩ */
+       0x046b, 499,    /* ѫ Ѫ */
+       0x046d, 499,    /* ѭ Ѭ */
+       0x046f, 499,    /* ѯ Ѯ */
+       0x0471, 499,    /* ѱ Ѱ */
+       0x0473, 499,    /* ѳ Ѳ */
+       0x0475, 499,    /* ѵ Ѵ */
+       0x0477, 499,    /* ѷ Ѷ */
+       0x0479, 499,    /* ѹ Ѹ */
+       0x047b, 499,    /* ѻ Ѻ */
+       0x047d, 499,    /* ѽ Ѽ */
+       0x047f, 499,    /* ѿ Ѿ */
+       0x0481, 499,    /* ҁ Ҁ */
+       0x0491, 499,    /* ґ Ґ */
+       0x0493, 499,    /* ғ Ғ */
+       0x0495, 499,    /* ҕ Ҕ */
+       0x0497, 499,    /* җ Җ */
+       0x0499, 499,    /* ҙ Ҙ */
+       0x049b, 499,    /* қ Қ */
+       0x049d, 499,    /* ҝ Ҝ */
+       0x049f, 499,    /* ҟ Ҟ */
+       0x04a1, 499,    /* ҡ Ҡ */
+       0x04a3, 499,    /* ң Ң */
+       0x04a5, 499,    /* ҥ Ҥ */
+       0x04a7, 499,    /* ҧ Ҧ */
+       0x04a9, 499,    /* ҩ Ҩ */
+       0x04ab, 499,    /* ҫ Ҫ */
+       0x04ad, 499,    /* ҭ Ҭ */
+       0x04af, 499,    /* ү Ү */
+       0x04b1, 499,    /* ұ Ұ */
+       0x04b3, 499,    /* ҳ Ҳ */
+       0x04b5, 499,    /* ҵ Ҵ */
+       0x04b7, 499,    /* ҷ Ҷ */
+       0x04b9, 499,    /* ҹ Ҹ */
+       0x04bb, 499,    /* һ Һ */
+       0x04bd, 499,    /* ҽ Ҽ */
+       0x04bf, 499,    /* ҿ Ҿ */
+       0x04c2, 499,    /* ӂ Ӂ */
+       0x04c4, 499,    /* ӄ Ӄ */
+       0x04c8, 499,    /* ӈ Ӈ */
+       0x04cc, 499,    /* ӌ Ӌ */
+       0x04d1, 499,    /* ӑ Ӑ */
+       0x04d3, 499,    /* ӓ Ӓ */
+       0x04d5, 499,    /* ӕ Ӕ */
+       0x04d7, 499,    /* ӗ Ӗ */
+       0x04d9, 499,    /* ә Ә */
+       0x04db, 499,    /* ӛ Ӛ */
+       0x04dd, 499,    /* ӝ Ӝ */
+       0x04df, 499,    /* ӟ Ӟ */
+       0x04e1, 499,    /* ӡ Ӡ */
+       0x04e3, 499,    /* ӣ Ӣ */
+       0x04e5, 499,    /* ӥ Ӥ */
+       0x04e7, 499,    /* ӧ Ӧ */
+       0x04e9, 499,    /* ө Ө */
+       0x04eb, 499,    /* ӫ Ӫ */
+       0x04ef, 499,    /* ӯ Ӯ */
+       0x04f1, 499,    /* ӱ Ӱ */
+       0x04f3, 499,    /* ӳ Ӳ */
+       0x04f5, 499,    /* ӵ Ӵ */
+       0x04f9, 499,    /* ӹ Ӹ */
+       0x1e01, 499,    /* ḁ Ḁ */
+       0x1e03, 499,    /* ḃ Ḃ */
+       0x1e05, 499,    /* ḅ Ḅ */
+       0x1e07, 499,    /* ḇ Ḇ */
+       0x1e09, 499,    /* ḉ Ḉ */
+       0x1e0b, 499,    /* ḋ Ḋ */
+       0x1e0d, 499,    /* ḍ Ḍ */
+       0x1e0f, 499,    /* ḏ Ḏ */
+       0x1e11, 499,    /* ḑ Ḑ */
+       0x1e13, 499,    /* ḓ Ḓ */
+       0x1e15, 499,    /* ḕ Ḕ */
+       0x1e17, 499,    /* ḗ Ḗ */
+       0x1e19, 499,    /* ḙ Ḙ */
+       0x1e1b, 499,    /* ḛ Ḛ */
+       0x1e1d, 499,    /* ḝ Ḝ */
+       0x1e1f, 499,    /* ḟ Ḟ */
+       0x1e21, 499,    /* ḡ Ḡ */
+       0x1e23, 499,    /* ḣ Ḣ */
+       0x1e25, 499,    /* ḥ Ḥ */
+       0x1e27, 499,    /* ḧ Ḧ */
+       0x1e29, 499,    /* ḩ Ḩ */
+       0x1e2b, 499,    /* ḫ Ḫ */
+       0x1e2d, 499,    /* ḭ Ḭ */
+       0x1e2f, 499,    /* ḯ Ḯ */
+       0x1e31, 499,    /* ḱ Ḱ */
+       0x1e33, 499,    /* ḳ Ḳ */
+       0x1e35, 499,    /* ḵ Ḵ */
+       0x1e37, 499,    /* ḷ Ḷ */
+       0x1e39, 499,    /* ḹ Ḹ */
+       0x1e3b, 499,    /* ḻ Ḻ */
+       0x1e3d, 499,    /* ḽ Ḽ */
+       0x1e3f, 499,    /* ḿ Ḿ */
+       0x1e41, 499,    /* ṁ Ṁ */
+       0x1e43, 499,    /* ṃ Ṃ */
+       0x1e45, 499,    /* ṅ Ṅ */
+       0x1e47, 499,    /* ṇ Ṇ */
+       0x1e49, 499,    /* ṉ Ṉ */
+       0x1e4b, 499,    /* ṋ Ṋ */
+       0x1e4d, 499,    /* ṍ Ṍ */
+       0x1e4f, 499,    /* ṏ Ṏ */
+       0x1e51, 499,    /* ṑ Ṑ */
+       0x1e53, 499,    /* ṓ Ṓ */
+       0x1e55, 499,    /* ṕ Ṕ */
+       0x1e57, 499,    /* ṗ Ṗ */
+       0x1e59, 499,    /* ṙ Ṙ */
+       0x1e5b, 499,    /* ṛ Ṛ */
+       0x1e5d, 499,    /* ṝ Ṝ */
+       0x1e5f, 499,    /* ṟ Ṟ */
+       0x1e61, 499,    /* ṡ Ṡ */
+       0x1e63, 499,    /* ṣ Ṣ */
+       0x1e65, 499,    /* ṥ Ṥ */
+       0x1e67, 499,    /* ṧ Ṧ */
+       0x1e69, 499,    /* ṩ Ṩ */
+       0x1e6b, 499,    /* ṫ Ṫ */
+       0x1e6d, 499,    /* ṭ Ṭ */
+       0x1e6f, 499,    /* ṯ Ṯ */
+       0x1e71, 499,    /* ṱ Ṱ */
+       0x1e73, 499,    /* ṳ Ṳ */
+       0x1e75, 499,    /* ṵ Ṵ */
+       0x1e77, 499,    /* ṷ Ṷ */
+       0x1e79, 499,    /* ṹ Ṹ */
+       0x1e7b, 499,    /* ṻ Ṻ */
+       0x1e7d, 499,    /* ṽ Ṽ */
+       0x1e7f, 499,    /* ṿ Ṿ */
+       0x1e81, 499,    /* ẁ Ẁ */
+       0x1e83, 499,    /* ẃ Ẃ */
+       0x1e85, 499,    /* ẅ Ẅ */
+       0x1e87, 499,    /* ẇ Ẇ */
+       0x1e89, 499,    /* ẉ Ẉ */
+       0x1e8b, 499,    /* ẋ Ẋ */
+       0x1e8d, 499,    /* ẍ Ẍ */
+       0x1e8f, 499,    /* ẏ Ẏ */
+       0x1e91, 499,    /* ẑ Ẑ */
+       0x1e93, 499,    /* ẓ Ẓ */
+       0x1e95, 499,    /* ẕ Ẕ */
+       0x1ea1, 499,    /* ạ Ạ */
+       0x1ea3, 499,    /* ả Ả */
+       0x1ea5, 499,    /* ấ Ấ */
+       0x1ea7, 499,    /* ầ Ầ */
+       0x1ea9, 499,    /* ẩ Ẩ */
+       0x1eab, 499,    /* ẫ Ẫ */
+       0x1ead, 499,    /* ậ Ậ */
+       0x1eaf, 499,    /* ắ Ắ */
+       0x1eb1, 499,    /* ằ Ằ */
+       0x1eb3, 499,    /* ẳ Ẳ */
+       0x1eb5, 499,    /* ẵ Ẵ */
+       0x1eb7, 499,    /* ặ Ặ */
+       0x1eb9, 499,    /* ẹ Ẹ */
+       0x1ebb, 499,    /* ẻ Ẻ */
+       0x1ebd, 499,    /* ẽ Ẽ */
+       0x1ebf, 499,    /* ế Ế */
+       0x1ec1, 499,    /* ề Ề */
+       0x1ec3, 499,    /* ể Ể */
+       0x1ec5, 499,    /* ễ Ễ */
+       0x1ec7, 499,    /* ệ Ệ */
+       0x1ec9, 499,    /* ỉ Ỉ */
+       0x1ecb, 499,    /* ị Ị */
+       0x1ecd, 499,    /* ọ Ọ */
+       0x1ecf, 499,    /* ỏ Ỏ */
+       0x1ed1, 499,    /* ố Ố */
+       0x1ed3, 499,    /* ồ Ồ */
+       0x1ed5, 499,    /* ổ Ổ */
+       0x1ed7, 499,    /* ỗ Ỗ */
+       0x1ed9, 499,    /* ộ Ộ */
+       0x1edb, 499,    /* ớ Ớ */
+       0x1edd, 499,    /* ờ Ờ */
+       0x1edf, 499,    /* ở Ở */
+       0x1ee1, 499,    /* ỡ Ỡ */
+       0x1ee3, 499,    /* ợ Ợ */
+       0x1ee5, 499,    /* ụ Ụ */
+       0x1ee7, 499,    /* ủ Ủ */
+       0x1ee9, 499,    /* ứ Ứ */
+       0x1eeb, 499,    /* ừ Ừ */
+       0x1eed, 499,    /* ử Ử */
+       0x1eef, 499,    /* ữ Ữ */
+       0x1ef1, 499,    /* ự Ự */
+       0x1ef3, 499,    /* ỳ Ỳ */
+       0x1ef5, 499,    /* ỵ Ỵ */
+       0x1ef7, 499,    /* ỷ Ỷ */
+       0x1ef9, 499,    /* ỹ Ỹ */
+       0x1f51, 508,    /* ὑ Ὑ */
+       0x1f53, 508,    /* ὓ Ὓ */
+       0x1f55, 508,    /* ὕ Ὕ */
+       0x1f57, 508,    /* ὗ Ὗ */
+       0x1fb3, 509,    /* ᾳ ᾼ */
+       0x1fc3, 509,    /* ῃ ῌ */
+       0x1fe5, 507,    /* ῥ Ῥ */
+       0x1ff3, 509,    /* ῳ ῼ */
+};
+
+/*
+ * upper case ranges
+ *     3rd col is conversion excess 500
+ */
+static
+Rune   __tolower2[] =
+{
+       0x0041, 0x005a, 532,    /* A-Z a-z */
+       0x00c0, 0x00d6, 532,    /* À-Ö à-ö */
+       0x00d8, 0x00de, 532,    /* Ø-Þ ø-þ */
+       0x0189, 0x018a, 705,    /* Ɖ-Ɗ ɖ-ɗ */
+       0x018e, 0x018f, 702,    /* Ǝ-Ə ɘ-ə */
+       0x01b1, 0x01b2, 717,    /* Ʊ-Ʋ ʊ-ʋ */
+       0x0388, 0x038a, 537,    /* Έ-Ί έ-ί */
+       0x038e, 0x038f, 563,    /* Ύ-Ώ ύ-ώ */
+       0x0391, 0x03a1, 532,    /* Α-Ρ α-ρ */
+       0x03a3, 0x03ab, 532,    /* Σ-Ϋ σ-ϋ */
+       0x0401, 0x040c, 580,    /* Ё-Ќ ё-ќ */
+       0x040e, 0x040f, 580,    /* Ў-Џ ў-џ */
+       0x0410, 0x042f, 532,    /* А-Я а-я */
+       0x0531, 0x0556, 548,    /* Ա-Ֆ ա-ֆ */
+       0x10a0, 0x10c5, 548,    /* Ⴀ-Ⴥ ა-ჵ */
+       0x1f08, 0x1f0f, 492,    /* Ἀ-Ἇ ἀ-ἇ */
+       0x1f18, 0x1f1d, 492,    /* Ἐ-Ἕ ἐ-ἕ */
+       0x1f28, 0x1f2f, 492,    /* Ἠ-Ἧ ἠ-ἧ */
+       0x1f38, 0x1f3f, 492,    /* Ἰ-Ἷ ἰ-ἷ */
+       0x1f48, 0x1f4d, 492,    /* Ὀ-Ὅ ὀ-ὅ */
+       0x1f68, 0x1f6f, 492,    /* Ὠ-Ὧ ὠ-ὧ */
+       0x1f88, 0x1f8f, 492,    /* ᾈ-ᾏ ᾀ-ᾇ */
+       0x1f98, 0x1f9f, 492,    /* ᾘ-ᾟ ᾐ-ᾗ */
+       0x1fa8, 0x1faf, 492,    /* ᾨ-ᾯ ᾠ-ᾧ */
+       0x1fb8, 0x1fb9, 492,    /* Ᾰ-Ᾱ ᾰ-ᾱ */
+       0x1fba, 0x1fbb, 426,    /* Ὰ-Ά ὰ-ά */
+       0x1fc8, 0x1fcb, 414,    /* Ὲ-Ή ὲ-ή */
+       0x1fd8, 0x1fd9, 492,    /* Ῐ-Ῑ ῐ-ῑ */
+       0x1fda, 0x1fdb, 400,    /* Ὶ-Ί ὶ-ί */
+       0x1fe8, 0x1fe9, 492,    /* Ῠ-Ῡ ῠ-ῡ */
+       0x1fea, 0x1feb, 388,    /* Ὺ-Ύ ὺ-ύ */
+       0x1ff8, 0x1ff9, 372,    /* Ὸ-Ό ὸ-ό */
+       0x1ffa, 0x1ffb, 374,    /* Ὼ-Ώ ὼ-ώ */
+       0x2160, 0x216f, 516,    /* Ⅰ-Ⅿ ⅰ-ⅿ */
+       0x24b6, 0x24cf, 526,    /* Ⓐ-Ⓩ ⓐ-ⓩ */
+       0xff21, 0xff3a, 532,    /* A-Z a-z */
+};
+
+/*
+ * upper case singlets
+ *     2nd col is conversion excess 500
+ */
+static
+Rune   __tolower1[] =
+{
+       0x0100, 501,    /* Ā ā */
+       0x0102, 501,    /* Ă ă */
+       0x0104, 501,    /* Ą ą */
+       0x0106, 501,    /* Ć ć */
+       0x0108, 501,    /* Ĉ ĉ */
+       0x010a, 501,    /* Ċ ċ */
+       0x010c, 501,    /* Č č */
+       0x010e, 501,    /* Ď ď */
+       0x0110, 501,    /* Đ đ */
+       0x0112, 501,    /* Ē ē */
+       0x0114, 501,    /* Ĕ ĕ */
+       0x0116, 501,    /* Ė ė */
+       0x0118, 501,    /* Ę ę */
+       0x011a, 501,    /* Ě ě */
+       0x011c, 501,    /* Ĝ ĝ */
+       0x011e, 501,    /* Ğ ğ */
+       0x0120, 501,    /* Ġ ġ */
+       0x0122, 501,    /* Ģ ģ */
+       0x0124, 501,    /* Ĥ ĥ */
+       0x0126, 501,    /* Ħ ħ */
+       0x0128, 501,    /* Ĩ ĩ */
+       0x012a, 501,    /* Ī ī */
+       0x012c, 501,    /* Ĭ ĭ */
+       0x012e, 501,    /* Į į */
+       0x0130, 301,    /* İ i */
+       0x0132, 501,    /* IJ ij */
+       0x0134, 501,    /* Ĵ ĵ */
+       0x0136, 501,    /* Ķ ķ */
+       0x0139, 501,    /* Ĺ ĺ */
+       0x013b, 501,    /* Ļ ļ */
+       0x013d, 501,    /* Ľ ľ */
+       0x013f, 501,    /* Ŀ ŀ */
+       0x0141, 501,    /* Ł ł */
+       0x0143, 501,    /* Ń ń */
+       0x0145, 501,    /* Ņ ņ */
+       0x0147, 501,    /* Ň ň */
+       0x014a, 501,    /* Ŋ ŋ */
+       0x014c, 501,    /* Ō ō */
+       0x014e, 501,    /* Ŏ ŏ */
+       0x0150, 501,    /* Ő ő */
+       0x0152, 501,    /* Œ œ */
+       0x0154, 501,    /* Ŕ ŕ */
+       0x0156, 501,    /* Ŗ ŗ */
+       0x0158, 501,    /* Ř ř */
+       0x015a, 501,    /* Ś ś */
+       0x015c, 501,    /* Ŝ ŝ */
+       0x015e, 501,    /* Ş ş */
+       0x0160, 501,    /* Š š */
+       0x0162, 501,    /* Ţ ţ */
+       0x0164, 501,    /* Ť ť */
+       0x0166, 501,    /* Ŧ ŧ */
+       0x0168, 501,    /* Ũ ũ */
+       0x016a, 501,    /* Ū ū */
+       0x016c, 501,    /* Ŭ ŭ */
+       0x016e, 501,    /* Ů ů */
+       0x0170, 501,    /* Ű ű */
+       0x0172, 501,    /* Ų ų */
+       0x0174, 501,    /* Ŵ ŵ */
+       0x0176, 501,    /* Ŷ ŷ */
+       0x0178, 379,    /* Ÿ ÿ */
+       0x0179, 501,    /* Ź ź */
+       0x017b, 501,    /* Ż ż */
+       0x017d, 501,    /* Ž ž */
+       0x0181, 710,    /* Ɓ ɓ */
+       0x0182, 501,    /* Ƃ ƃ */
+       0x0184, 501,    /* Ƅ ƅ */
+       0x0186, 706,    /* Ɔ ɔ */
+       0x0187, 501,    /* Ƈ ƈ */
+       0x018b, 501,    /* Ƌ ƌ */
+       0x0190, 703,    /* Ɛ ɛ */
+       0x0191, 501,    /* Ƒ ƒ */
+       0x0193, 705,    /* Ɠ ɠ */
+       0x0194, 707,    /* Ɣ ɣ */
+       0x0196, 711,    /* Ɩ ɩ */
+       0x0197, 709,    /* Ɨ ɨ */
+       0x0198, 501,    /* Ƙ ƙ */
+       0x019c, 711,    /* Ɯ ɯ */
+       0x019d, 713,    /* Ɲ ɲ */
+       0x01a0, 501,    /* Ơ ơ */
+       0x01a2, 501,    /* Ƣ ƣ */
+       0x01a4, 501,    /* Ƥ ƥ */
+       0x01a7, 501,    /* Ƨ ƨ */
+       0x01a9, 718,    /* Ʃ ʃ */
+       0x01ac, 501,    /* Ƭ ƭ */
+       0x01ae, 718,    /* Ʈ ʈ */
+       0x01af, 501,    /* Ư ư */
+       0x01b3, 501,    /* Ƴ ƴ */
+       0x01b5, 501,    /* Ƶ ƶ */
+       0x01b7, 719,    /* Ʒ ʒ */
+       0x01b8, 501,    /* Ƹ ƹ */
+       0x01bc, 501,    /* Ƽ ƽ */
+       0x01c4, 502,    /* DŽ dž */
+       0x01c5, 501,    /* Dž dž */
+       0x01c7, 502,    /* LJ lj */
+       0x01c8, 501,    /* Lj lj */
+       0x01ca, 502,    /* NJ nj */
+       0x01cb, 501,    /* Nj nj */
+       0x01cd, 501,    /* Ǎ ǎ */
+       0x01cf, 501,    /* Ǐ ǐ */
+       0x01d1, 501,    /* Ǒ ǒ */
+       0x01d3, 501,    /* Ǔ ǔ */
+       0x01d5, 501,    /* Ǖ ǖ */
+       0x01d7, 501,    /* Ǘ ǘ */
+       0x01d9, 501,    /* Ǚ ǚ */
+       0x01db, 501,    /* Ǜ ǜ */
+       0x01de, 501,    /* Ǟ ǟ */
+       0x01e0, 501,    /* Ǡ ǡ */
+       0x01e2, 501,    /* Ǣ ǣ */
+       0x01e4, 501,    /* Ǥ ǥ */
+       0x01e6, 501,    /* Ǧ ǧ */
+       0x01e8, 501,    /* Ǩ ǩ */
+       0x01ea, 501,    /* Ǫ ǫ */
+       0x01ec, 501,    /* Ǭ ǭ */
+       0x01ee, 501,    /* Ǯ ǯ */
+       0x01f1, 502,    /* DZ dz */
+       0x01f2, 501,    /* Dz dz */
+       0x01f4, 501,    /* Ǵ ǵ */
+       0x01fa, 501,    /* Ǻ ǻ */
+       0x01fc, 501,    /* Ǽ ǽ */
+       0x01fe, 501,    /* Ǿ ǿ */
+       0x0200, 501,    /* Ȁ ȁ */
+       0x0202, 501,    /* Ȃ ȃ */
+       0x0204, 501,    /* Ȅ ȅ */
+       0x0206, 501,    /* Ȇ ȇ */
+       0x0208, 501,    /* Ȉ ȉ */
+       0x020a, 501,    /* Ȋ ȋ */
+       0x020c, 501,    /* Ȍ ȍ */
+       0x020e, 501,    /* Ȏ ȏ */
+       0x0210, 501,    /* Ȑ ȑ */
+       0x0212, 501,    /* Ȓ ȓ */
+       0x0214, 501,    /* Ȕ ȕ */
+       0x0216, 501,    /* Ȗ ȗ */
+       0x0386, 538,    /* Ά ά */
+       0x038c, 564,    /* Ό ό */
+       0x03e2, 501,    /* Ϣ ϣ */
+       0x03e4, 501,    /* Ϥ ϥ */
+       0x03e6, 501,    /* Ϧ ϧ */
+       0x03e8, 501,    /* Ϩ ϩ */
+       0x03ea, 501,    /* Ϫ ϫ */
+       0x03ec, 501,    /* Ϭ ϭ */
+       0x03ee, 501,    /* Ϯ ϯ */
+       0x0460, 501,    /* Ѡ ѡ */
+       0x0462, 501,    /* Ѣ ѣ */
+       0x0464, 501,    /* Ѥ ѥ */
+       0x0466, 501,    /* Ѧ ѧ */
+       0x0468, 501,    /* Ѩ ѩ */
+       0x046a, 501,    /* Ѫ ѫ */
+       0x046c, 501,    /* Ѭ ѭ */
+       0x046e, 501,    /* Ѯ ѯ */
+       0x0470, 501,    /* Ѱ ѱ */
+       0x0472, 501,    /* Ѳ ѳ */
+       0x0474, 501,    /* Ѵ ѵ */
+       0x0476, 501,    /* Ѷ ѷ */
+       0x0478, 501,    /* Ѹ ѹ */
+       0x047a, 501,    /* Ѻ ѻ */
+       0x047c, 501,    /* Ѽ ѽ */
+       0x047e, 501,    /* Ѿ ѿ */
+       0x0480, 501,    /* Ҁ ҁ */
+       0x0490, 501,    /* Ґ ґ */
+       0x0492, 501,    /* Ғ ғ */
+       0x0494, 501,    /* Ҕ ҕ */
+       0x0496, 501,    /* Җ җ */
+       0x0498, 501,    /* Ҙ ҙ */
+       0x049a, 501,    /* Қ қ */
+       0x049c, 501,    /* Ҝ ҝ */
+       0x049e, 501,    /* Ҟ ҟ */
+       0x04a0, 501,    /* Ҡ ҡ */
+       0x04a2, 501,    /* Ң ң */
+       0x04a4, 501,    /* Ҥ ҥ */
+       0x04a6, 501,    /* Ҧ ҧ */
+       0x04a8, 501,    /* Ҩ ҩ */
+       0x04aa, 501,    /* Ҫ ҫ */
+       0x04ac, 501,    /* Ҭ ҭ */
+       0x04ae, 501,    /* Ү ү */
+       0x04b0, 501,    /* Ұ ұ */
+       0x04b2, 501,    /* Ҳ ҳ */
+       0x04b4, 501,    /* Ҵ ҵ */
+       0x04b6, 501,    /* Ҷ ҷ */
+       0x04b8, 501,    /* Ҹ ҹ */
+       0x04ba, 501,    /* Һ һ */
+       0x04bc, 501,    /* Ҽ ҽ */
+       0x04be, 501,    /* Ҿ ҿ */
+       0x04c1, 501,    /* Ӂ ӂ */
+       0x04c3, 501,    /* Ӄ ӄ */
+       0x04c7, 501,    /* Ӈ ӈ */
+       0x04cb, 501,    /* Ӌ ӌ */
+       0x04d0, 501,    /* Ӑ ӑ */
+       0x04d2, 501,    /* Ӓ ӓ */
+       0x04d4, 501,    /* Ӕ ӕ */
+       0x04d6, 501,    /* Ӗ ӗ */
+       0x04d8, 501,    /* Ә ә */
+       0x04da, 501,    /* Ӛ ӛ */
+       0x04dc, 501,    /* Ӝ ӝ */
+       0x04de, 501,    /* Ӟ ӟ */
+       0x04e0, 501,    /* Ӡ ӡ */
+       0x04e2, 501,    /* Ӣ ӣ */
+       0x04e4, 501,    /* Ӥ ӥ */
+       0x04e6, 501,    /* Ӧ ӧ */
+       0x04e8, 501,    /* Ө ө */
+       0x04ea, 501,    /* Ӫ ӫ */
+       0x04ee, 501,    /* Ӯ ӯ */
+       0x04f0, 501,    /* Ӱ ӱ */
+       0x04f2, 501,    /* Ӳ ӳ */
+       0x04f4, 501,    /* Ӵ ӵ */
+       0x04f8, 501,    /* Ӹ ӹ */
+       0x1e00, 501,    /* Ḁ ḁ */
+       0x1e02, 501,    /* Ḃ ḃ */
+       0x1e04, 501,    /* Ḅ ḅ */
+       0x1e06, 501,    /* Ḇ ḇ */
+       0x1e08, 501,    /* Ḉ ḉ */
+       0x1e0a, 501,    /* Ḋ ḋ */
+       0x1e0c, 501,    /* Ḍ ḍ */
+       0x1e0e, 501,    /* Ḏ ḏ */
+       0x1e10, 501,    /* Ḑ ḑ */
+       0x1e12, 501,    /* Ḓ ḓ */
+       0x1e14, 501,    /* Ḕ ḕ */
+       0x1e16, 501,    /* Ḗ ḗ */
+       0x1e18, 501,    /* Ḙ ḙ */
+       0x1e1a, 501,    /* Ḛ ḛ */
+       0x1e1c, 501,    /* Ḝ ḝ */
+       0x1e1e, 501,    /* Ḟ ḟ */
+       0x1e20, 501,    /* Ḡ ḡ */
+       0x1e22, 501,    /* Ḣ ḣ */
+       0x1e24, 501,    /* Ḥ ḥ */
+       0x1e26, 501,    /* Ḧ ḧ */
+       0x1e28, 501,    /* Ḩ ḩ */
+       0x1e2a, 501,    /* Ḫ ḫ */
+       0x1e2c, 501,    /* Ḭ ḭ */
+       0x1e2e, 501,    /* Ḯ ḯ */
+       0x1e30, 501,    /* Ḱ ḱ */
+       0x1e32, 501,    /* Ḳ ḳ */
+       0x1e34, 501,    /* Ḵ ḵ */
+       0x1e36, 501,    /* Ḷ ḷ */
+       0x1e38, 501,    /* Ḹ ḹ */
+       0x1e3a, 501,    /* Ḻ ḻ */
+       0x1e3c, 501,    /* Ḽ ḽ */
+       0x1e3e, 501,    /* Ḿ ḿ */
+       0x1e40, 501,    /* Ṁ ṁ */
+       0x1e42, 501,    /* Ṃ ṃ */
+       0x1e44, 501,    /* Ṅ ṅ */
+       0x1e46, 501,    /* Ṇ ṇ */
+       0x1e48, 501,    /* Ṉ ṉ */
+       0x1e4a, 501,    /* Ṋ ṋ */
+       0x1e4c, 501,    /* Ṍ ṍ */
+       0x1e4e, 501,    /* Ṏ ṏ */
+       0x1e50, 501,    /* Ṑ ṑ */
+       0x1e52, 501,    /* Ṓ ṓ */
+       0x1e54, 501,    /* Ṕ ṕ */
+       0x1e56, 501,    /* Ṗ ṗ */
+       0x1e58, 501,    /* Ṙ ṙ */
+       0x1e5a, 501,    /* Ṛ ṛ */
+       0x1e5c, 501,    /* Ṝ ṝ */
+       0x1e5e, 501,    /* Ṟ ṟ */
+       0x1e60, 501,    /* Ṡ ṡ */
+       0x1e62, 501,    /* Ṣ ṣ */
+       0x1e64, 501,    /* Ṥ ṥ */
+       0x1e66, 501,    /* Ṧ ṧ */
+       0x1e68, 501,    /* Ṩ ṩ */
+       0x1e6a, 501,    /* Ṫ ṫ */
+       0x1e6c, 501,    /* Ṭ ṭ */
+       0x1e6e, 501,    /* Ṯ ṯ */
+       0x1e70, 501,    /* Ṱ ṱ */
+       0x1e72, 501,    /* Ṳ ṳ */
+       0x1e74, 501,    /* Ṵ ṵ */
+       0x1e76, 501,    /* Ṷ ṷ */
+       0x1e78, 501,    /* Ṹ ṹ */
+       0x1e7a, 501,    /* Ṻ ṻ */
+       0x1e7c, 501,    /* Ṽ ṽ */
+       0x1e7e, 501,    /* Ṿ ṿ */
+       0x1e80, 501,    /* Ẁ ẁ */
+       0x1e82, 501,    /* Ẃ ẃ */
+       0x1e84, 501,    /* Ẅ ẅ */
+       0x1e86, 501,    /* Ẇ ẇ */
+       0x1e88, 501,    /* Ẉ ẉ */
+       0x1e8a, 501,    /* Ẋ ẋ */
+       0x1e8c, 501,    /* Ẍ ẍ */
+       0x1e8e, 501,    /* Ẏ ẏ */
+       0x1e90, 501,    /* Ẑ ẑ */
+       0x1e92, 501,    /* Ẓ ẓ */
+       0x1e94, 501,    /* Ẕ ẕ */
+       0x1ea0, 501,    /* Ạ ạ */
+       0x1ea2, 501,    /* Ả ả */
+       0x1ea4, 501,    /* Ấ ấ */
+       0x1ea6, 501,    /* Ầ ầ */
+       0x1ea8, 501,    /* Ẩ ẩ */
+       0x1eaa, 501,    /* Ẫ ẫ */
+       0x1eac, 501,    /* Ậ ậ */
+       0x1eae, 501,    /* Ắ ắ */
+       0x1eb0, 501,    /* Ằ ằ */
+       0x1eb2, 501,    /* Ẳ ẳ */
+       0x1eb4, 501,    /* Ẵ ẵ */
+       0x1eb6, 501,    /* Ặ ặ */
+       0x1eb8, 501,    /* Ẹ ẹ */
+       0x1eba, 501,    /* Ẻ ẻ */
+       0x1ebc, 501,    /* Ẽ ẽ */
+       0x1ebe, 501,    /* Ế ế */
+       0x1ec0, 501,    /* Ề ề */
+       0x1ec2, 501,    /* Ể ể */
+       0x1ec4, 501,    /* Ễ ễ */
+       0x1ec6, 501,    /* Ệ ệ */
+       0x1ec8, 501,    /* Ỉ ỉ */
+       0x1eca, 501,    /* Ị ị */
+       0x1ecc, 501,    /* Ọ ọ */
+       0x1ece, 501,    /* Ỏ ỏ */
+       0x1ed0, 501,    /* Ố ố */
+       0x1ed2, 501,    /* Ồ ồ */
+       0x1ed4, 501,    /* Ổ ổ */
+       0x1ed6, 501,    /* Ỗ ỗ */
+       0x1ed8, 501,    /* Ộ ộ */
+       0x1eda, 501,    /* Ớ ớ */
+       0x1edc, 501,    /* Ờ ờ */
+       0x1ede, 501,    /* Ở ở */
+       0x1ee0, 501,    /* Ỡ ỡ */
+       0x1ee2, 501,    /* Ợ ợ */
+       0x1ee4, 501,    /* Ụ ụ */
+       0x1ee6, 501,    /* Ủ ủ */
+       0x1ee8, 501,    /* Ứ ứ */
+       0x1eea, 501,    /* Ừ ừ */
+       0x1eec, 501,    /* Ử ử */
+       0x1eee, 501,    /* Ữ ữ */
+       0x1ef0, 501,    /* Ự ự */
+       0x1ef2, 501,    /* Ỳ ỳ */
+       0x1ef4, 501,    /* Ỵ ỵ */
+       0x1ef6, 501,    /* Ỷ ỷ */
+       0x1ef8, 501,    /* Ỹ ỹ */
+       0x1f59, 492,    /* Ὑ ὑ */
+       0x1f5b, 492,    /* Ὓ ὓ */
+       0x1f5d, 492,    /* Ὕ ὕ */
+       0x1f5f, 492,    /* Ὗ ὗ */
+       0x1fbc, 491,    /* ᾼ ᾳ */
+       0x1fcc, 491,    /* ῌ ῃ */
+       0x1fec, 493,    /* Ῥ ῥ */
+       0x1ffc, 491,    /* ῼ ῳ */
+};
+
+/*
+ * title characters are those between
+ * upper and lower case. ie DZ Dz dz
+ */
+static
+Rune   __totitle1[] =
+{
+       0x01c4, 501,    /* DŽ Dž */
+       0x01c6, 499,    /* dž Dž */
+       0x01c7, 501,    /* LJ Lj */
+       0x01c9, 499,    /* lj Lj */
+       0x01ca, 501,    /* NJ Nj */
+       0x01cc, 499,    /* nj Nj */
+       0x01f1, 501,    /* DZ Dz */
+       0x01f3, 499,    /* dz Dz */
+};
+
+static Rune*
+bsearch(Rune c, Rune *t, int n, int ne)
+{
+       Rune *p;
+       int m;
+
+       while(n > 1) {
+               m = n/2;
+               p = t + m*ne;
+               if(c >= p[0]) {
+                       t = p;
+                       n = n-m;
+               } else
+                       n = m;
+       }
+       if(n && c >= t[0])
+               return t;
+       return 0;
+}
+
+Rune
+tolowerrune(Rune c)
+{
+       Rune *p;
+
+       p = bsearch(c, __tolower2, nelem(__tolower2)/3, 3);
+       if(p && c >= p[0] && c <= p[1])
+               return c + p[2] - 500;
+       p = bsearch(c, __tolower1, nelem(__tolower1)/2, 2);
+       if(p && c == p[0])
+               return c + p[1] - 500;
+       return c;
+}
+
+Rune
+toupperrune(Rune c)
+{
+       Rune *p;
+
+       p = bsearch(c, __toupper2, nelem(__toupper2)/3, 3);
+       if(p && c >= p[0] && c <= p[1])
+               return c + p[2] - 500;
+       p = bsearch(c, __toupper1, nelem(__toupper1)/2, 2);
+       if(p && c == p[0])
+               return c + p[1] - 500;
+       return c;
+}
+
+Rune
+totitlerune(Rune c)
+{
+       Rune *p;
+
+       p = bsearch(c, __totitle1, nelem(__totitle1)/2, 2);
+       if(p && c == p[0])
+               return c + p[1] - 500;
+       return c;
+}
+
+int
+islowerrune(Rune c)
+{
+       Rune *p;
+
+       p = bsearch(c, __toupper2, nelem(__toupper2)/3, 3);
+       if(p && c >= p[0] && c <= p[1])
+               return 1;
+       p = bsearch(c, __toupper1, nelem(__toupper1)/2, 2);
+       if(p && c == p[0])
+               return 1;
+       return 0;
+}
+
+int
+isupperrune(Rune c)
+{
+       Rune *p;
+
+       p = bsearch(c, __tolower2, nelem(__tolower2)/3, 3);
+       if(p && c >= p[0] && c <= p[1])
+               return 1;
+       p = bsearch(c, __tolower1, nelem(__tolower1)/2, 2);
+       if(p && c == p[0])
+               return 1;
+       return 0;
+}
+
+int
+isalpharune(Rune c)
+{
+       Rune *p;
+
+       if(isupperrune(c) || islowerrune(c))
+               return 1;
+       p = bsearch(c, __alpha2, nelem(__alpha2)/2, 2);
+       if(p && c >= p[0] && c <= p[1])
+               return 1;
+       p = bsearch(c, __alpha1, nelem(__alpha1), 1);
+       if(p && c == p[0])
+               return 1;
+       return 0;
+}
+
+int
+istitlerune(Rune c)
+{
+       return isupperrune(c) && islowerrune(c);
+}
+
+int
+isspacerune(Rune c)
+{
+       Rune *p;
+
+       p = bsearch(c, __space2, nelem(__space2)/2, 2);
+       if(p && c >= p[0] && c <= p[1])
+               return 1;
+       return 0;
+}
diff --git a/src/lib9/utf/utfdef.h b/src/lib9/utf/utfdef.h
new file mode 100644 (file)
index 0000000..ba3749a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 1998-2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/*
+ * compiler directive on Plan 9
+ */
+#ifndef USED
+#define USED(x) if(x);else
+#endif
+
+/*
+ * easiest way to make sure these are defined
+ */
+#define uchar  _fmtuchar
+#define ushort _fmtushort
+#define uint   _fmtuint
+#define ulong  _fmtulong
+#define vlong  _fmtvlong
+#define uvlong _fmtuvlong
+typedef unsigned char          uchar;
+typedef unsigned short         ushort;
+typedef unsigned int           uint;
+typedef unsigned long          ulong;
+typedef unsigned long long     uvlong;
+typedef long long              vlong;
+
+/*
+ * nil cannot be ((void*)0) on ANSI C,
+ * because it is used for function pointers
+ */
+#undef nil
+#define        nil     0
+
+#undef nelem
+#define        nelem   ((void*)0)
+
diff --git a/src/lib9/utf/utfecpy.c b/src/lib9/utf/utfecpy.c
new file mode 100644 (file)
index 0000000..cf3535f
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#define _BSD_SOURCE 1  /* memccpy */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+char*
+utfecpy(char *to, char *e, char *from)
+{
+       char *end;
+
+       if(to >= e)
+               return to;
+       end = memccpy(to, from, '\0', e - to);
+       if(end == nil){
+               end = e-1;
+               while(end>to && (*--end&0xC0)==0x80)
+                       ;
+               *end = '\0';
+       }else{
+               end--;
+       }
+       return end;
+}
diff --git a/src/lib9/utf/utflen.c b/src/lib9/utf/utflen.c
new file mode 100644 (file)
index 0000000..769805a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+int
+utflen(char *s)
+{
+       int c;
+       long n;
+       Rune rune;
+
+       n = 0;
+       for(;;) {
+               c = *(uchar*)s;
+               if(c < Runeself) {
+                       if(c == 0)
+                               return n;
+                       s++;
+               } else
+                       s += chartorune(&rune, s);
+               n++;
+       }
+}
diff --git a/src/lib9/utf/utfnlen.c b/src/lib9/utf/utfnlen.c
new file mode 100644 (file)
index 0000000..6680329
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+int
+utfnlen(char *s, long m)
+{
+       int c;
+       long n;
+       Rune rune;
+       char *es;
+
+       es = s + m;
+       for(n = 0; s < es; n++) {
+               c = *(uchar*)s;
+               if(c < Runeself){
+                       if(c == '\0')
+                               break;
+                       s++;
+                       continue;
+               }
+               if(!fullrune(s, es-s))
+                       break;
+               s += chartorune(&rune, s);
+       }
+       return n;
+}
diff --git a/src/lib9/utf/utfrrune.c b/src/lib9/utf/utfrrune.c
new file mode 100644 (file)
index 0000000..cff12b5
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+char*
+utfrrune(char *s, long c)
+{
+       long c1;
+       Rune r;
+       char *s1;
+
+       if(c < Runesync)                /* not part of utf sequence */
+               return strrchr(s, c);
+
+       s1 = 0;
+       for(;;) {
+               c1 = *(uchar*)s;
+               if(c1 < Runeself) {     /* one byte rune */
+                       if(c1 == 0)
+                               return s1;
+                       if(c1 == c)
+                               s1 = s;
+                       s++;
+                       continue;
+               }
+               c1 = chartorune(&r, s);
+               if(r == c)
+                       s1 = s;
+               s += c1;
+       }
+}
diff --git a/src/lib9/utf/utfrune.c b/src/lib9/utf/utfrune.c
new file mode 100644 (file)
index 0000000..52b8359
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+char*
+utfrune(char *s, long c)
+{
+       long c1;
+       Rune r;
+       int n;
+
+       if(c < Runesync)                /* not part of utf sequence */
+               return strchr(s, c);
+
+       for(;;) {
+               c1 = *(uchar*)s;
+               if(c1 < Runeself) {     /* one byte rune */
+                       if(c1 == 0)
+                               return 0;
+                       if(c1 == c)
+                               return s;
+                       s++;
+                       continue;
+               }
+               n = chartorune(&r, s);
+               if(r == c)
+                       return s;
+               s += n;
+       }
+}
diff --git a/src/lib9/utf/utfutf.c b/src/lib9/utf/utfutf.c
new file mode 100644 (file)
index 0000000..13c8502
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
+ * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include "plan9.h"
+#include "utf.h"
+
+
+/*
+ * Return pointer to first occurrence of s2 in s1,
+ * 0 if none
+ */
+char*
+utfutf(char *s1, char *s2)
+{
+       char *p;
+       long f, n1, n2;
+       Rune r;
+
+       n1 = chartorune(&r, s2);
+       f = r;
+       if(f <= Runesync)               /* represents self */
+               return strstr(s1, s2);
+
+       n2 = strlen(s2);
+       for(p=s1; p=utfrune(p, f); p+=n1)
+               if(strncmp(p, s2, n2) == 0)
+                       return p;
+       return 0;
+}
diff --git a/src/libbio/Makefile b/src/libbio/Makefile
new file mode 100644 (file)
index 0000000..eddeac0
--- /dev/null
@@ -0,0 +1,64 @@
+# Derived from http://code.google.com/p/inferno-os/source/browse/libbio/mkfile
+#
+#      Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+#      Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+#      Portions Copyright © 2009 The Go Authors.  All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+CFLAGS=-I$(GOROOT)/include
+O=o
+
+LIB=libbio.a
+
+OFILES=\
+       bbuffered.$O\
+       bfildes.$O\
+       bflush.$O\
+       bgetc.$O\
+       bgetrune.$O\
+       bgetd.$O\
+       binit.$O\
+       boffset.$O\
+       bprint.$O\
+       bputc.$O\
+       bputrune.$O\
+       brdline.$O\
+       brdstr.$O\
+       bread.$O\
+       bseek.$O\
+       bwrite.$O\
+
+HFILES=\
+       $(GOROOT)/include/bio.h\
+
+install: $(LIB)
+       cp $(LIB) $(GOROOT)/lib
+
+$(LIB): $(OFILES)
+       ar rsc $(LIB) $(OFILES)
+
+$(OFILES): $(HFILES)
+
+y.tab.c: $(YFILES)
+       yacc $(YFLAGS) $(YFILES)
+
+clean:
+       rm -f $(OFILES) *.6 6.out $(LIB)
+
diff --git a/src/libbio/bbuffered.c b/src/libbio/bbuffered.c
new file mode 100644 (file)
index 0000000..2ddb29b
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bbuffered.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+int
+Bbuffered(Biobuf *bp)
+{
+       switch(bp->state) {
+       case Bracteof:
+       case Bractive:
+               return -bp->icount;
+
+       case Bwactive:
+               return bp->bsize + bp->ocount;
+
+       case Binactive:
+               return 0;
+       }
+       fprint(2, "Bbuffered: unknown state %d\n", bp->state);
+       return 0;
+}
diff --git a/src/libbio/bfildes.c b/src/libbio/bfildes.c
new file mode 100644 (file)
index 0000000..aef1f70
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bfildes.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+int
+Bfildes(Biobuf *bp)
+{
+
+       return bp->fid;
+}
diff --git a/src/libbio/bflush.c b/src/libbio/bflush.c
new file mode 100644 (file)
index 0000000..8a071cb
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bflush.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+int
+Bflush(Biobuf *bp)
+{
+       int n, c;
+
+       switch(bp->state) {
+       case Bwactive:
+               n = bp->bsize+bp->ocount;
+               if(n == 0)
+                       return 0;
+               c = write(bp->fid, bp->bbuf, n);
+               if(n == c) {
+                       bp->offset += n;
+                       bp->ocount = -bp->bsize;
+                       return 0;
+               }
+               bp->state = Binactive;
+               bp->ocount = 0;
+               break;
+
+       case Bracteof:
+               bp->state = Bractive;
+
+       case Bractive:
+               bp->icount = 0;
+               bp->gbuf = bp->ebuf;
+               return 0;
+       }
+       return Beof;
+}
diff --git a/src/libbio/bgetc.c b/src/libbio/bgetc.c
new file mode 100644 (file)
index 0000000..52ed241
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bgetc.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+int
+Bgetc(Biobuf *bp)
+{
+       int i;
+
+loop:
+       i = bp->icount;
+       if(i != 0) {
+               bp->icount = i+1;
+               return bp->ebuf[i];
+       }
+       if(bp->state != Bractive) {
+               if(bp->state == Bracteof)
+                       bp->state = Bractive;
+               return Beof;
+       }
+       /*
+        * get next buffer, try to keep Bungetsize
+        * characters pre-catenated from the previous
+        * buffer to allow that many ungets.
+        */
+       memmove(bp->bbuf-Bungetsize, bp->ebuf-Bungetsize, Bungetsize);
+       i = read(bp->fid, bp->bbuf, bp->bsize);
+       bp->gbuf = bp->bbuf;
+       if(i <= 0) {
+               bp->state = Bracteof;
+               if(i < 0)
+                       bp->state = Binactive;
+               return Beof;
+       }
+       if(i < bp->bsize) {
+               memmove(bp->ebuf-i-Bungetsize, bp->bbuf-Bungetsize, i+Bungetsize);
+               bp->gbuf = bp->ebuf-i;
+       }
+       bp->icount = -i;
+       bp->offset += i;
+       goto loop;
+}
+
+int
+Bungetc(Biobuf *bp)
+{
+
+       if(bp->state == Bracteof)
+               bp->state = Bractive;
+       if(bp->state != Bractive)
+               return Beof;
+       bp->icount--;
+       return 1;
+}
diff --git a/src/libbio/bgetd.c b/src/libbio/bgetd.c
new file mode 100644 (file)
index 0000000..cf76a75
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bgetd.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include <bio.h>
+
+struct bgetd
+{
+       Biobuf* b;
+       int             eof;
+};
+
+static int
+Bgetdf(void *vp)
+{
+       int c;
+       struct bgetd *bg = vp;
+
+       c = Bgetc(bg->b);
+       if(c == Beof)
+               bg->eof = 1;
+       return c;
+}
+
+int
+Bgetd(Biobuf *bp, double *dp)
+{
+       double d;
+       struct bgetd b;
+
+       b.b = bp;
+       b.eof = 0;
+       d = fmtcharstod(Bgetdf, &b);
+       if(b.eof)
+               return -1;
+       Bungetc(bp);
+       *dp = d;
+       return 1;
+}
diff --git a/src/libbio/bgetrune.c b/src/libbio/bgetrune.c
new file mode 100644 (file)
index 0000000..caeb0a8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bgetrune.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+#include       <utf.h>
+
+long
+Bgetrune(Biobuf *bp)
+{
+       int c, i;
+       Rune rune;
+       char str[4];
+
+       c = Bgetc(bp);
+       if(c < Runeself) {              /* one char */
+               bp->runesize = 1;
+               return c;
+       }
+       str[0] = c;
+
+       for(i=1;;) {
+               c = Bgetc(bp);
+               if(c < 0)
+                       return c;
+               str[i++] = c;
+
+               if(fullrune(str, i)) {
+                       bp->runesize = chartorune(&rune, str);
+                       while(i > bp->runesize) {
+                               Bungetc(bp);
+                               i--;
+                       }
+                       return rune;
+               }
+       }
+}
+
+int
+Bungetrune(Biobuf *bp)
+{
+
+       if(bp->state == Bracteof)
+               bp->state = Bractive;
+       if(bp->state != Bractive)
+               return Beof;
+       bp->icount -= bp->runesize;
+       bp->runesize = 0;
+       return 1;
+}
diff --git a/src/libbio/binit.c b/src/libbio/binit.c
new file mode 100644 (file)
index 0000000..6eb7776
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/binit.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+enum
+{
+       MAXBUFS = 20
+};
+
+static Biobuf* wbufs[MAXBUFS];
+static int             atexitflag;
+
+static
+void
+batexit(void)
+{
+       Biobuf *bp;
+       int i;
+
+       for(i=0; i<MAXBUFS; i++) {
+               bp = wbufs[i];
+               if(bp != 0) {
+                       wbufs[i] = 0;
+                       Bflush(bp);
+               }
+       }
+}
+
+static
+void
+deinstall(Biobuf *bp)
+{
+       int i;
+
+       for(i=0; i<MAXBUFS; i++)
+               if(wbufs[i] == bp)
+                       wbufs[i] = 0;
+}
+
+static
+void
+install(Biobuf *bp)
+{
+       int i;
+
+       deinstall(bp);
+       for(i=0; i<MAXBUFS; i++)
+               if(wbufs[i] == 0) {
+                       wbufs[i] = bp;
+                       break;
+               }
+       if(atexitflag == 0) {
+               atexitflag = 1;
+               atexit(batexit);
+       }
+}
+
+int
+Binits(Biobuf *bp, int f, int mode, unsigned char *p, int size)
+{
+
+       p += Bungetsize;        /* make room for Bungets */
+       size -= Bungetsize;
+
+       switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) {
+       default:
+               fprint(2, "Bopen: unknown mode %d\n", mode);
+               return Beof;
+
+       case OREAD:
+               bp->state = Bractive;
+               bp->ocount = 0;
+               break;
+
+       case OWRITE:
+               install(bp);
+               bp->state = Bwactive;
+               bp->ocount = -size;
+               break;
+       }
+       bp->bbuf = p;
+       bp->ebuf = p+size;
+       bp->bsize = size;
+       bp->icount = 0;
+       bp->gbuf = bp->ebuf;
+       bp->fid = f;
+       bp->flag = 0;
+       bp->rdline = 0;
+       bp->offset = 0;
+       bp->runesize = 0;
+       return 0;
+}
+
+
+int
+Binit(Biobuf *bp, int f, int mode)
+{
+       return Binits(bp, f, mode, bp->b, sizeof(bp->b));
+}
+
+Biobuf*
+Bfdopen(int f, int mode)
+{
+       Biobuf *bp;
+
+       bp = malloc(sizeof(Biobuf));
+       if(bp == 0)
+               return 0;
+       Binits(bp, f, mode, bp->b, sizeof(bp->b));
+       bp->flag = Bmagic;
+       return bp;
+}
+
+Biobuf*
+Bopen(char *name, int mode)
+{
+       Biobuf *bp;
+       int f;
+
+       switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) {
+       default:
+               fprint(2, "Bopen: unknown mode %d\n", mode);
+               return 0;
+
+       case OREAD:
+               f = open(name, OREAD);
+               if(f < 0)
+                       return 0;
+               break;
+
+       case OWRITE:
+               f = creat(name, 0666);
+               if(f < 0)
+                       return 0;
+       }
+       bp = Bfdopen(f, mode);
+       if(bp == 0)
+               close(f);
+       return bp;
+}
+
+int
+Bterm(Biobuf *bp)
+{
+
+       deinstall(bp);
+       Bflush(bp);
+       if(bp->flag == Bmagic) {
+               bp->flag = 0;
+               close(bp->fid);
+               free(bp);
+       }
+       return 0;
+}
diff --git a/src/libbio/boffset.c b/src/libbio/boffset.c
new file mode 100644 (file)
index 0000000..77d8b08
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/boffset.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       "lib9.h"
+#include       <bio.h>
+
+off_t
+Boffset(Biobuf *bp)
+{
+       off_t n;
+
+       switch(bp->state) {
+       default:
+               fprint(2, "Boffset: unknown state %d\n", bp->state);
+               n = Beof;
+               break;
+
+       case Bracteof:
+       case Bractive:
+               n = bp->offset + bp->icount;
+               break;
+
+       case Bwactive:
+               n = bp->offset + (bp->bsize + bp->ocount);
+               break;
+       }
+       return n;
+}
diff --git a/src/libbio/bprint.c b/src/libbio/bprint.c
new file mode 100644 (file)
index 0000000..2e3867a
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bprint.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+int
+Bprint(Biobuf *bp, char *fmt, ...)
+{
+        va_list ap;
+        char *ip, *ep, *out;
+        int n;
+
+        ep = (char*)bp->ebuf;
+        ip = ep + bp->ocount;
+        va_start(ap, fmt);
+        out = vseprint(ip, ep, fmt, ap);
+        va_end(ap);
+        if(out == nil || out >= ep-5) {
+                Bflush(bp);
+                ip = ep + bp->ocount;
+                va_start(ap, fmt);
+                out = vseprint(ip, ep, fmt, ap);
+                va_end(ap);
+                if(out >= ep-5)
+                        return Beof;
+        }
+        n = out-ip;
+        bp->ocount += n;
+        return n;
+}
diff --git a/src/libbio/bputc.c b/src/libbio/bputc.c
new file mode 100644 (file)
index 0000000..4cdbe8f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bputc.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+int
+Bputc(Biobuf *bp, int c)
+{
+       int i;
+
+       for(;;) {
+               i = bp->ocount;
+               if(i) {
+                       bp->ebuf[i++] = c;
+                       bp->ocount = i;
+                       return 0;
+               }
+               if(Bflush(bp) == Beof)
+                       break;
+       }
+       return Beof;
+}
diff --git a/src/libbio/bputrune.c b/src/libbio/bputrune.c
new file mode 100644 (file)
index 0000000..9c588db
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bputrune.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+#include       <utf.h>
+
+int
+Bputrune(Biobuf *bp, long c)
+{
+       Rune rune;
+       char str[4];
+       int n;
+
+       rune = c;
+       if(rune < Runeself) {
+               Bputc(bp, rune);
+               return 1;
+       }
+       n = runetochar(str, &rune);
+       if(n == 0)
+               return Bbad;
+       if(Bwrite(bp, str, n) != n)
+               return Beof;
+       return n;
+}
diff --git a/src/libbio/brdline.c b/src/libbio/brdline.c
new file mode 100644 (file)
index 0000000..a02bf10
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/brdline.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+void*
+Brdline(Biobuf *bp, int delim)
+{
+       char *ip, *ep;
+       int i, j;
+
+       i = -bp->icount;
+       if(i == 0) {
+               /*
+                * eof or other error
+                */
+               if(bp->state != Bractive) {
+                       if(bp->state == Bracteof)
+                               bp->state = Bractive;
+                       bp->rdline = 0;
+                       bp->gbuf = bp->ebuf;
+                       return 0;
+               }
+       }
+
+       /*
+        * first try in remainder of buffer (gbuf doesn't change)
+        */
+       ip = (char*)bp->ebuf - i;
+       ep = memchr(ip, delim, i);
+       if(ep) {
+               j = (ep - ip) + 1;
+               bp->rdline = j;
+               bp->icount += j;
+               return ip;
+       }
+
+       /*
+        * copy data to beginning of buffer
+        */
+       if(i < bp->bsize)
+               memmove(bp->bbuf, ip, i);
+       bp->gbuf = bp->bbuf;
+
+       /*
+        * append to buffer looking for the delim
+        */
+       ip = (char*)bp->bbuf + i;
+       while(i < bp->bsize) {
+               j = read(bp->fid, ip, bp->bsize-i);
+               if(j <= 0) {
+                       /*
+                        * end of file with no delim
+                        */
+                       memmove(bp->ebuf-i, bp->bbuf, i);
+                       bp->rdline = i;
+                       bp->icount = -i;
+                       bp->gbuf = bp->ebuf-i;
+                       return 0;
+               }
+               bp->offset += j;
+               i += j;
+               ep = memchr(ip, delim, j);
+               if(ep) {
+                       /*
+                        * found in new piece
+                        * copy back up and reset everything
+                        */
+                       ip = (char*)bp->ebuf - i;
+                       if(i < bp->bsize){
+                               memmove(ip, bp->bbuf, i);
+                               bp->gbuf = (unsigned char*)ip;
+                       }
+                       j = (ep - (char*)bp->bbuf) + 1;
+                       bp->rdline = j;
+                       bp->icount = j - i;
+                       return ip;
+               }
+               ip += j;
+       }
+
+       /*
+        * full buffer without finding
+        */
+       bp->rdline = bp->bsize;
+       bp->icount = -bp->bsize;
+       bp->gbuf = bp->bbuf;
+       return 0;
+}
+
+int
+Blinelen(Biobuf *bp)
+{
+
+       return bp->rdline;
+}
diff --git a/src/libbio/brdstr.c b/src/libbio/brdstr.c
new file mode 100644 (file)
index 0000000..0398ab0
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+       Copyright © 2009 The Go Authors.  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+char*
+Brdstr(Biobuf *bp, int delim, int nulldelim)
+{
+       char *p, *q, *nq;
+       int n, linelen;
+
+       q = nil;
+       n = 0;
+       for(;;) {
+               p = Brdline(bp, delim);
+               linelen = Blinelen(bp);
+               if(n == 0 && linelen == 0)
+                       return nil;
+               nq = realloc(q, n+linelen+1);
+               if(nq == nil) {
+                       free(q);
+                       return nil;
+               }
+               q = nq;
+               if(p != nil) {
+                       memmove(q+n, p, linelen);
+                       n += linelen;
+                       if(nulldelim)
+                               q[n-1] = '\0';
+                       break;
+               }
+               if(linelen == 0)
+                       break;
+               Bread(bp, q+n, linelen);
+               n += linelen;
+       }
+       q[n] = '\0';
+       return q;
+}
diff --git a/src/libbio/bread.c b/src/libbio/bread.c
new file mode 100644 (file)
index 0000000..5cf9a05
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bread.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+long
+Bread(Biobuf *bp, void *ap, long count)
+{
+       long c;
+       unsigned char *p;
+       int i, n, ic;
+
+       p = ap;
+       c = count;
+       ic = bp->icount;
+
+       while(c > 0) {
+               n = -ic;
+               if(n > c)
+                       n = c;
+               if(n == 0) {
+                       if(bp->state != Bractive)
+                               break;
+                       i = read(bp->fid, bp->bbuf, bp->bsize);
+                       if(i <= 0) {
+                               bp->state = Bracteof;
+                               if(i < 0)
+                                       bp->state = Binactive;
+                               break;
+                       }
+                       bp->gbuf = bp->bbuf;
+                       bp->offset += i;
+                       if(i < bp->bsize) {
+                               memmove(bp->ebuf-i, bp->bbuf, i);
+                               bp->gbuf = bp->ebuf-i;
+                       }
+                       ic = -i;
+                       continue;
+               }
+               memmove(p, bp->ebuf+ic, n);
+               c -= n;
+               ic += n;
+               p += n;
+       }
+       bp->icount = ic;
+       return count-c;
+}
diff --git a/src/libbio/bseek.c b/src/libbio/bseek.c
new file mode 100644 (file)
index 0000000..d60aeeb
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bseek.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       "lib9.h"
+#include       <bio.h>
+
+off_t
+Bseek(Biobuf *bp, off_t offset, int base)
+{
+       vlong n, d;
+       int bufsz;
+
+       switch(bp->state) {
+       default:
+               fprint(2, "Bseek: unknown state %d\n", bp->state);
+               return Beof;
+
+       case Bracteof:
+               bp->state = Bractive;
+               bp->icount = 0;
+               bp->gbuf = bp->ebuf;
+
+       case Bractive:
+               n = offset;
+               if(base == 1) {
+                       n += Boffset(bp);
+                       base = 0;
+               }
+
+               /*
+                * try to seek within buffer
+                */
+               if(base == 0) {
+                       d = n - Boffset(bp);
+                       bufsz = bp->ebuf - bp->gbuf;
+                       if(-bufsz <= d && d <= bufsz){
+                               bp->icount += d;
+                               if(d >= 0) {
+                                       if(bp->icount <= 0)
+                                               return n;
+                               } else {
+                                       if(bp->ebuf - bp->gbuf >= -bp->icount)
+                                               return n;
+                               }
+                       }
+               }
+
+               /*
+                * reset the buffer
+                */
+               n = lseek(bp->fid, n, base);
+               bp->icount = 0;
+               bp->gbuf = bp->ebuf;
+               break;
+
+       case Bwactive:
+               Bflush(bp);
+               n = lseek(bp->fid, offset, base);
+               break;
+       }
+       bp->offset = n;
+       return n;
+}
diff --git a/src/libbio/bwrite.c b/src/libbio/bwrite.c
new file mode 100644 (file)
index 0000000..daed161
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+http://code.google.com/p/inferno-os/source/browse/libbio/bwrite.c
+
+       Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+       Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+
+long
+Bwrite(Biobuf *bp, void *ap, long count)
+{
+       long c;
+       unsigned char *p;
+       int i, n, oc;
+
+       p = ap;
+       c = count;
+       oc = bp->ocount;
+
+       while(c > 0) {
+               n = -oc;
+               if(n > c)
+                       n = c;
+               if(n == 0) {
+                       if(bp->state != Bwactive)
+                               return Beof;
+                       i = write(bp->fid, bp->bbuf, bp->bsize);
+                       if(i != bp->bsize) {
+                               bp->state = Binactive;
+                               return Beof;
+                       }
+                       bp->offset += i;
+                       oc = -bp->bsize;
+                       continue;
+               }
+               memmove(bp->ebuf+oc, p, n);
+               oc += n;
+               c -= n;
+               p += n;
+       }
+       bp->ocount = oc;
+       return count-c;
+}
index 9a21cfe2da01989a995887f653a0ca118bbbd96b..e81a2a4e5fb6cfa3222cec7280bcaba38648388d 100755 (executable)
@@ -3,6 +3,13 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
+for i in lib9 libbio
+do
+       cd $i
+       make install
+       cd ..
+done
+
 for i in cmd runtime
 do
        cd $i
diff --git a/src/runtime/clean.bash b/src/runtime/clean.bash
new file mode 100644 (file)
index 0000000..df20318
--- /dev/null
@@ -0,0 +1,5 @@
+# Copyright 2009 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+echo nothing to clean here
index 4bbcdf56c9dacb0c66045a2bd018b373c131c28e..50c3793be5933ace66a917a37afd497e90266a2c 100644 (file)
@@ -105,8 +105,7 @@ hello world
 =========== ken/simpvar.go
 
 =========== ken/string.go
-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-index 0<12700>6
-throw: bounds
+abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz
 
 =========== ken/strvar.go