Initial revision
This commit is contained in:
79
include/bio.h
Normal file
79
include/bio.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef _BIOH_
|
||||
#define _BIOH_ 1
|
||||
|
||||
#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*);
|
||||
int Bfildes(Biobuf*);
|
||||
int Bflush(Biobuf*);
|
||||
int Bgetc(Biobuf*);
|
||||
int Bgetd(Biobuf*, double*);
|
||||
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);
|
||||
void* Brdline(Biobuf*, int);
|
||||
long Bread(Biobuf*, void*, long);
|
||||
off_t Bseek(Biobuf*, off_t, int);
|
||||
int Bterm(Biobuf*);
|
||||
int Bungetc(Biobuf*);
|
||||
long Bwrite(Biobuf*, void*, long);
|
||||
char* Brdstr(Biobuf*, int, int);
|
||||
long Bgetrune(Biobuf*);
|
||||
int Bputrune(Biobuf*, long);
|
||||
|
||||
#endif
|
||||
7
include/cursor.h
Normal file
7
include/cursor.h
Normal file
@@ -0,0 +1,7 @@
|
||||
typedef struct Cursor Cursor;
|
||||
struct Cursor
|
||||
{
|
||||
Point offset;
|
||||
uchar clr[2*16];
|
||||
uchar set[2*16];
|
||||
};
|
||||
520
include/draw.h
Normal file
520
include/draw.h
Normal file
@@ -0,0 +1,520 @@
|
||||
typedef struct Cachefont Cachefont;
|
||||
typedef struct Cacheinfo Cacheinfo;
|
||||
typedef struct Cachesubf Cachesubf;
|
||||
typedef struct Display Display;
|
||||
typedef struct Font Font;
|
||||
typedef struct Fontchar Fontchar;
|
||||
typedef struct Image Image;
|
||||
typedef struct Mouse Mouse;
|
||||
typedef struct Point Point;
|
||||
typedef struct Rectangle Rectangle;
|
||||
typedef struct RGB RGB;
|
||||
typedef struct Screen Screen;
|
||||
typedef struct Subfont Subfont;
|
||||
|
||||
extern int Rfmt(Fmt*);
|
||||
extern int Pfmt(Fmt*);
|
||||
|
||||
enum
|
||||
{
|
||||
DOpaque = 0xFFFFFFFF,
|
||||
DTransparent = 0x00000000, /* only useful for allocimage, memfillcolor */
|
||||
DBlack = 0x000000FF,
|
||||
DWhite = 0xFFFFFFFF,
|
||||
DRed = 0xFF0000FF,
|
||||
DGreen = 0x00FF00FF,
|
||||
DBlue = 0x0000FFFF,
|
||||
DCyan = 0x00FFFFFF,
|
||||
DMagenta = 0xFF00FFFF,
|
||||
DYellow = 0xFFFF00FF,
|
||||
DPaleyellow = 0xFFFFAAFF,
|
||||
DDarkyellow = 0xEEEE9EFF,
|
||||
DDarkgreen = 0x448844FF,
|
||||
DPalegreen = 0xAAFFAAFF,
|
||||
DMedgreen = 0x88CC88FF,
|
||||
DDarkblue = 0x000055FF,
|
||||
DPalebluegreen= 0xAAFFFFFF,
|
||||
DPaleblue = 0x0000BBFF,
|
||||
DBluegreen = 0x008888FF,
|
||||
DGreygreen = 0x55AAAAFF,
|
||||
DPalegreygreen = 0x9EEEEEFF,
|
||||
DYellowgreen = 0x99994CFF,
|
||||
DMedblue = 0x000099FF,
|
||||
DGreyblue = 0x005DBBFF,
|
||||
DPalegreyblue = 0x4993DDFF,
|
||||
DPurpleblue = 0x8888CCFF,
|
||||
|
||||
DNotacolor = 0xFFFFFF00,
|
||||
DNofill = DNotacolor,
|
||||
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Displaybufsize = 8000,
|
||||
ICOSSCALE = 1024,
|
||||
Borderwidth = 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* refresh methods */
|
||||
Refbackup = 0,
|
||||
Refnone = 1,
|
||||
Refmesg = 2
|
||||
};
|
||||
#define NOREFRESH ((void*)-1)
|
||||
|
||||
enum
|
||||
{
|
||||
/* line ends */
|
||||
Endsquare = 0,
|
||||
Enddisc = 1,
|
||||
Endarrow = 2,
|
||||
Endmask = 0x1F
|
||||
};
|
||||
|
||||
#define ARROW(a, b, c) (Endarrow|((a)<<5)|((b)<<14)|((c)<<23))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Porter-Duff compositing operators */
|
||||
Clear = 0,
|
||||
|
||||
SinD = 8,
|
||||
DinS = 4,
|
||||
SoutD = 2,
|
||||
DoutS = 1,
|
||||
|
||||
S = SinD|SoutD,
|
||||
SoverD = SinD|SoutD|DoutS,
|
||||
SatopD = SinD|DoutS,
|
||||
SxorD = SoutD|DoutS,
|
||||
|
||||
D = DinS|DoutS,
|
||||
DoverS = DinS|DoutS|SoutD,
|
||||
DatopS = DinS|SoutD,
|
||||
DxorS = DoutS|SoutD, /* == SxorD */
|
||||
|
||||
Ncomp = 12,
|
||||
} Drawop;
|
||||
|
||||
/*
|
||||
* image channel descriptors
|
||||
*/
|
||||
enum {
|
||||
CRed = 0,
|
||||
CGreen,
|
||||
CBlue,
|
||||
CGrey,
|
||||
CAlpha,
|
||||
CMap,
|
||||
CIgnore,
|
||||
NChan,
|
||||
};
|
||||
|
||||
#define __DC(type, nbits) ((((type)&15)<<4)|((nbits)&15))
|
||||
#define CHAN1(a,b) __DC(a,b)
|
||||
#define CHAN2(a,b,c,d) (CHAN1((a),(b))<<8|__DC((c),(d)))
|
||||
#define CHAN3(a,b,c,d,e,f) (CHAN2((a),(b),(c),(d))<<8|__DC((e),(f)))
|
||||
#define CHAN4(a,b,c,d,e,f,g,h) (CHAN3((a),(b),(c),(d),(e),(f))<<8|__DC((g),(h)))
|
||||
|
||||
#define NBITS(c) ((c)&15)
|
||||
#define TYPE(c) (((c)>>4)&15)
|
||||
|
||||
enum {
|
||||
GREY1 = CHAN1(CGrey, 1),
|
||||
GREY2 = CHAN1(CGrey, 2),
|
||||
GREY4 = CHAN1(CGrey, 4),
|
||||
GREY8 = CHAN1(CGrey, 8),
|
||||
CMAP8 = CHAN1(CMap, 8),
|
||||
RGB15 = CHAN4(CIgnore, 1, CRed, 5, CGreen, 5, CBlue, 5),
|
||||
RGB16 = CHAN3(CRed, 5, CGreen, 6, CBlue, 5),
|
||||
RGB24 = CHAN3(CRed, 8, CGreen, 8, CBlue, 8),
|
||||
BGR24 = CHAN3(CBlue, 8, CGreen, 8, CRed, 8),
|
||||
RGBA32 = CHAN4(CRed, 8, CGreen, 8, CBlue, 8, CAlpha, 8),
|
||||
ARGB32 = CHAN4(CAlpha, 8, CRed, 8, CGreen, 8, CBlue, 8), /* stupid VGAs */
|
||||
XRGB32 = CHAN4(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8),
|
||||
XBGR32 = CHAN4(CIgnore, 8, CBlue, 8, CGreen, 8, CRed, 8),
|
||||
};
|
||||
|
||||
extern char* chantostr(char*, u32int);
|
||||
extern u32int strtochan(char*);
|
||||
extern int chantodepth(u32int);
|
||||
|
||||
struct Point
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct Rectangle
|
||||
{
|
||||
Point min;
|
||||
Point max;
|
||||
};
|
||||
|
||||
typedef void (*Reffn)(Image*, Rectangle, void*);
|
||||
|
||||
struct Screen
|
||||
{
|
||||
Display *display; /* display holding data */
|
||||
int id; /* id of system-held Screen */
|
||||
Image *image; /* unused; for reference only */
|
||||
Image *fill; /* color to paint behind windows */
|
||||
};
|
||||
|
||||
struct Display
|
||||
{
|
||||
QLock qlock;
|
||||
int locking; /*program is using lockdisplay */
|
||||
int dirno;
|
||||
int imageid;
|
||||
int local;
|
||||
void (*error)(Display*, char*);
|
||||
char *devdir;
|
||||
char *windir;
|
||||
char oldlabel[64];
|
||||
u32int dataqid;
|
||||
Image *image;
|
||||
Image *white;
|
||||
Image *black;
|
||||
Image *opaque;
|
||||
Image *transparent;
|
||||
uchar *buf;
|
||||
int bufsize;
|
||||
uchar *bufp;
|
||||
uchar *obuf;
|
||||
int obufsize;
|
||||
uchar *obufp;
|
||||
Font *defaultfont;
|
||||
Subfont *defaultsubfont;
|
||||
Image *windows;
|
||||
Image *screenimage;
|
||||
int _isnewdisplay;
|
||||
};
|
||||
|
||||
struct Image
|
||||
{
|
||||
Display *display; /* display holding data */
|
||||
int id; /* id of system-held Image */
|
||||
Rectangle r; /* rectangle in data area, local coords */
|
||||
Rectangle clipr; /* clipping region */
|
||||
int depth; /* number of bits per pixel */
|
||||
u32int chan;
|
||||
int repl; /* flag: data replicates to tile clipr */
|
||||
Screen *screen; /* 0 if not a window */
|
||||
Image *next; /* next in list of windows */
|
||||
};
|
||||
|
||||
struct RGB
|
||||
{
|
||||
u32int red;
|
||||
u32int green;
|
||||
u32int blue;
|
||||
};
|
||||
|
||||
/*
|
||||
* Subfonts
|
||||
*
|
||||
* given char c, Subfont *f, Fontchar *i, and Point p, one says
|
||||
* i = f->info+c;
|
||||
* draw(b, Rect(p.x+i->left, p.y+i->top,
|
||||
* p.x+i->left+((i+1)->x-i->x), p.y+i->bottom),
|
||||
* color, f->bits, Pt(i->x, i->top));
|
||||
* p.x += i->width;
|
||||
* to draw characters in the specified color (itself an Image) in Image b.
|
||||
*/
|
||||
|
||||
struct Fontchar
|
||||
{
|
||||
int x; /* left edge of bits */
|
||||
uchar top; /* first non-zero scan-line */
|
||||
uchar bottom; /* last non-zero scan-line + 1 */
|
||||
char left; /* offset of baseline */
|
||||
uchar width; /* width of baseline */
|
||||
};
|
||||
|
||||
struct Subfont
|
||||
{
|
||||
char *name;
|
||||
short n; /* number of chars in font */
|
||||
uchar height; /* height of image */
|
||||
char ascent; /* top of image to baseline */
|
||||
Fontchar *info; /* n+1 character descriptors */
|
||||
Image *bits; /* of font */
|
||||
int ref;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* starting values */
|
||||
LOG2NFCACHE = 6,
|
||||
NFCACHE = (1<<LOG2NFCACHE), /* #chars cached */
|
||||
NFLOOK = 5, /* #chars to scan in cache */
|
||||
NFSUBF = 2, /* #subfonts to cache */
|
||||
/* max value */
|
||||
MAXFCACHE = 1024+NFLOOK, /* upper limit */
|
||||
MAXSUBF = 50, /* generous upper limit */
|
||||
/* deltas */
|
||||
DSUBF = 4,
|
||||
/* expiry ages */
|
||||
SUBFAGE = 10000,
|
||||
CACHEAGE = 10000
|
||||
};
|
||||
|
||||
struct Cachefont
|
||||
{
|
||||
Rune min; /* lowest rune value to be taken from subfont */
|
||||
Rune max; /* highest rune value+1 to be taken from subfont */
|
||||
int offset; /* position in subfont of character at min */
|
||||
char *name; /* stored in font */
|
||||
char *subfontname; /* to access subfont */
|
||||
};
|
||||
|
||||
struct Cacheinfo
|
||||
{
|
||||
ushort x; /* left edge of bits */
|
||||
uchar width; /* width of baseline */
|
||||
schar left; /* offset of baseline */
|
||||
Rune value; /* value of character at this slot in cache */
|
||||
ushort age;
|
||||
};
|
||||
|
||||
struct Cachesubf
|
||||
{
|
||||
u32int age; /* for replacement */
|
||||
Cachefont *cf; /* font info that owns us */
|
||||
Subfont *f; /* attached subfont */
|
||||
};
|
||||
|
||||
struct Font
|
||||
{
|
||||
char *name;
|
||||
Display *display;
|
||||
short height; /* max height of image, interline spacing */
|
||||
short ascent; /* top of image to baseline */
|
||||
short width; /* widest so far; used in caching only */
|
||||
short nsub; /* number of subfonts */
|
||||
u32int age; /* increasing counter; used for LRU */
|
||||
int maxdepth; /* maximum depth of all loaded subfonts */
|
||||
int ncache; /* size of cache */
|
||||
int nsubf; /* size of subfont list */
|
||||
Cacheinfo *cache;
|
||||
Cachesubf *subf;
|
||||
Cachefont **sub; /* as read from file */
|
||||
Image *cacheimage;
|
||||
};
|
||||
|
||||
#define Dx(r) ((r).max.x-(r).min.x)
|
||||
#define Dy(r) ((r).max.y-(r).min.y)
|
||||
|
||||
/*
|
||||
* Image management
|
||||
*/
|
||||
extern Image* _allocimage(Image*, Display*, Rectangle, u32int, int, u32int, int, int);
|
||||
extern Image* allocimage(Display*, Rectangle, u32int, int, u32int);
|
||||
extern uchar* bufimage(Display*, int);
|
||||
extern int bytesperline(Rectangle, int);
|
||||
extern void closedisplay(Display*);
|
||||
extern void drawerror(Display*, char*);
|
||||
extern int flushimage(Display*, int);
|
||||
extern int freeimage(Image*);
|
||||
extern int _freeimage1(Image*);
|
||||
extern int geninitdraw(char*, void(*)(Display*, char*), char*, char*, char*, int);
|
||||
extern int initdraw(void(*)(Display*, char*), char*, char*);
|
||||
extern int newwindow(char*);
|
||||
extern int loadimage(Image*, Rectangle, uchar*, int);
|
||||
extern int cloadimage(Image*, Rectangle, uchar*, int);
|
||||
extern int getwindow(Display*, int);
|
||||
extern int gengetwindow(Display*, char*, Image**, Screen**, int);
|
||||
extern Image* readimage(Display*, int, int);
|
||||
extern Image* creadimage(Display*, int, int);
|
||||
extern int unloadimage(Image*, Rectangle, uchar*, int);
|
||||
extern int wordsperline(Rectangle, int);
|
||||
extern int writeimage(int, Image*, int);
|
||||
extern Image* namedimage(Display*, char*);
|
||||
extern int nameimage(Image*, char*, int);
|
||||
extern Image* allocimagemix(Display*, u32int, u32int);
|
||||
|
||||
/*
|
||||
* Colors
|
||||
*/
|
||||
extern void readcolmap(Display*, RGB*);
|
||||
extern void writecolmap(Display*, RGB*);
|
||||
extern u32int setalpha(u32int, uchar);
|
||||
|
||||
/*
|
||||
* Windows
|
||||
*/
|
||||
extern Screen* allocscreen(Image*, Image*, int);
|
||||
extern Image* _allocwindow(Image*, Screen*, Rectangle, int, u32int);
|
||||
extern Image* allocwindow(Screen*, Rectangle, int, u32int);
|
||||
extern void bottomnwindows(Image**, int);
|
||||
extern void bottomwindow(Image*);
|
||||
extern int freescreen(Screen*);
|
||||
extern Screen* publicscreen(Display*, int, u32int);
|
||||
extern void topnwindows(Image**, int);
|
||||
extern void topwindow(Image*);
|
||||
extern int originwindow(Image*, Point, Point);
|
||||
|
||||
/*
|
||||
* Geometry
|
||||
*/
|
||||
extern Point Pt(int, int);
|
||||
extern Rectangle Rect(int, int, int, int);
|
||||
extern Rectangle Rpt(Point, Point);
|
||||
extern Point addpt(Point, Point);
|
||||
extern Point subpt(Point, Point);
|
||||
extern Point divpt(Point, int);
|
||||
extern Point mulpt(Point, int);
|
||||
extern int eqpt(Point, Point);
|
||||
extern int eqrect(Rectangle, Rectangle);
|
||||
extern Rectangle insetrect(Rectangle, int);
|
||||
extern Rectangle rectaddpt(Rectangle, Point);
|
||||
extern Rectangle rectsubpt(Rectangle, Point);
|
||||
extern Rectangle canonrect(Rectangle);
|
||||
extern int rectXrect(Rectangle, Rectangle);
|
||||
extern int rectinrect(Rectangle, Rectangle);
|
||||
extern void combinerect(Rectangle*, Rectangle);
|
||||
extern int rectclip(Rectangle*, Rectangle);
|
||||
extern int ptinrect(Point, Rectangle);
|
||||
extern void replclipr(Image*, int, Rectangle);
|
||||
extern int drawreplxy(int, int, int); /* used to be drawsetxy */
|
||||
extern Point drawrepl(Rectangle, Point);
|
||||
extern int rgb2cmap(int, int, int);
|
||||
extern int cmap2rgb(int);
|
||||
extern int cmap2rgba(int);
|
||||
extern void icossin(int, int*, int*);
|
||||
extern void icossin2(int, int, int*, int*);
|
||||
|
||||
/*
|
||||
* Graphics
|
||||
*/
|
||||
extern void draw(Image*, Rectangle, Image*, Image*, Point);
|
||||
extern void drawop(Image*, Rectangle, Image*, Image*, Point, Drawop);
|
||||
extern void gendraw(Image*, Rectangle, Image*, Point, Image*, Point);
|
||||
extern void gendrawop(Image*, Rectangle, Image*, Point, Image*, Point, Drawop);
|
||||
extern void line(Image*, Point, Point, int, int, int, Image*, Point);
|
||||
extern void lineop(Image*, Point, Point, int, int, int, Image*, Point, Drawop);
|
||||
extern void poly(Image*, Point*, int, int, int, int, Image*, Point);
|
||||
extern void polyop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
|
||||
extern void fillpoly(Image*, Point*, int, int, Image*, Point);
|
||||
extern void fillpolyop(Image*, Point*, int, int, Image*, Point, Drawop);
|
||||
extern Point string(Image*, Point, Image*, Point, Font*, char*);
|
||||
extern Point stringop(Image*, Point, Image*, Point, Font*, char*, Drawop);
|
||||
extern Point stringn(Image*, Point, Image*, Point, Font*, char*, int);
|
||||
extern Point stringnop(Image*, Point, Image*, Point, Font*, char*, int, Drawop);
|
||||
extern Point runestring(Image*, Point, Image*, Point, Font*, Rune*);
|
||||
extern Point runestringop(Image*, Point, Image*, Point, Font*, Rune*, Drawop);
|
||||
extern Point runestringn(Image*, Point, Image*, Point, Font*, Rune*, int);
|
||||
extern Point runestringnop(Image*, Point, Image*, Point, Font*, Rune*, int, Drawop);
|
||||
extern Point stringbg(Image*, Point, Image*, Point, Font*, char*, Image*, Point);
|
||||
extern Point stringbgop(Image*, Point, Image*, Point, Font*, char*, Image*, Point, Drawop);
|
||||
extern Point stringnbg(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point);
|
||||
extern Point stringnbgop(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point, Drawop);
|
||||
extern Point runestringbg(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point);
|
||||
extern Point runestringbgop(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point, Drawop);
|
||||
extern Point runestringnbg(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point);
|
||||
extern Point runestringnbgop(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point, Drawop);
|
||||
extern Point _string(Image*, Point, Image*, Point, Font*, char*, Rune*, int, Rectangle, Image*, Point, Drawop);
|
||||
extern Point stringsubfont(Image*, Point, Image*, Subfont*, char*);
|
||||
extern int bezier(Image*, Point, Point, Point, Point, int, int, int, Image*, Point);
|
||||
extern int bezierop(Image*, Point, Point, Point, Point, int, int, int, Image*, Point, Drawop);
|
||||
extern int bezspline(Image*, Point*, int, int, int, int, Image*, Point);
|
||||
extern int bezsplineop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
|
||||
extern int bezsplinepts(Point*, int, Point**);
|
||||
extern int fillbezier(Image*, Point, Point, Point, Point, int, Image*, Point);
|
||||
extern int fillbezierop(Image*, Point, Point, Point, Point, int, Image*, Point, Drawop);
|
||||
extern int fillbezspline(Image*, Point*, int, int, Image*, Point);
|
||||
extern int fillbezsplineop(Image*, Point*, int, int, Image*, Point, Drawop);
|
||||
extern void ellipse(Image*, Point, int, int, int, Image*, Point);
|
||||
extern void ellipseop(Image*, Point, int, int, int, Image*, Point, Drawop);
|
||||
extern void fillellipse(Image*, Point, int, int, Image*, Point);
|
||||
extern void fillellipseop(Image*, Point, int, int, Image*, Point, Drawop);
|
||||
extern void arc(Image*, Point, int, int, int, Image*, Point, int, int);
|
||||
extern void arcop(Image*, Point, int, int, int, Image*, Point, int, int, Drawop);
|
||||
extern void fillarc(Image*, Point, int, int, Image*, Point, int, int);
|
||||
extern void fillarcop(Image*, Point, int, int, Image*, Point, int, int, Drawop);
|
||||
extern void border(Image*, Rectangle, int, Image*, Point);
|
||||
extern void borderop(Image*, Rectangle, int, Image*, Point, Drawop);
|
||||
|
||||
/*
|
||||
* Font management
|
||||
*/
|
||||
extern Font* openfont(Display*, char*);
|
||||
extern Font* buildfont(Display*, char*, char*);
|
||||
extern void freefont(Font*);
|
||||
extern Font* mkfont(Subfont*, Rune);
|
||||
extern int cachechars(Font*, char**, Rune**, ushort*, int, int*, char**);
|
||||
extern void agefont(Font*);
|
||||
extern Subfont* allocsubfont(char*, int, int, int, Fontchar*, Image*);
|
||||
extern Subfont* lookupsubfont(Display*, char*);
|
||||
extern void installsubfont(char*, Subfont*);
|
||||
extern void uninstallsubfont(Subfont*);
|
||||
extern void freesubfont(Subfont*);
|
||||
extern Subfont* readsubfont(Display*, char*, int, int);
|
||||
extern Subfont* readsubfonti(Display*, char*, int, Image*, int);
|
||||
extern int writesubfont(int, Subfont*);
|
||||
extern void _unpackinfo(Fontchar*, uchar*, int);
|
||||
extern Point stringsize(Font*, char*);
|
||||
extern int stringwidth(Font*, char*);
|
||||
extern int stringnwidth(Font*, char*, int);
|
||||
extern Point runestringsize(Font*, Rune*);
|
||||
extern int runestringwidth(Font*, Rune*);
|
||||
extern int runestringnwidth(Font*, Rune*, int);
|
||||
extern Point strsubfontwidth(Subfont*, char*);
|
||||
extern int loadchar(Font*, Rune, Cacheinfo*, int, int, char**);
|
||||
extern char* subfontname(char*, char*, int);
|
||||
extern Subfont* _getsubfont(Display*, char*);
|
||||
extern Subfont* getdefont(Display*);
|
||||
extern void lockdisplay(Display*);
|
||||
extern void unlockdisplay(Display*);
|
||||
extern int drawlsetrefresh(u32int, int, void*, void*);
|
||||
|
||||
/*
|
||||
* Predefined
|
||||
*/
|
||||
extern uchar defontdata[];
|
||||
extern int sizeofdefont;
|
||||
extern Point ZP;
|
||||
extern Rectangle ZR;
|
||||
|
||||
/*
|
||||
* Set up by initdraw()
|
||||
*/
|
||||
extern Display *display;
|
||||
extern Font *font;
|
||||
extern Image *screen;
|
||||
extern Screen *_screen;
|
||||
extern int _cursorfd;
|
||||
extern int _drawdebug; /* set to 1 to see errors from flushimage */
|
||||
extern void _setdrawop(Display*, Drawop);
|
||||
extern Display *_initdisplay(void(*)(Display*,char*), char*);
|
||||
|
||||
#define BGSHORT(p) (((p)[0]<<0) | ((p)[1]<<8))
|
||||
#define BGLONG(p) ((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16))
|
||||
#define BPSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8))
|
||||
#define BPLONG(p, v) (BPSHORT(p, (v)), BPSHORT(p+2, (v)>>16))
|
||||
|
||||
/*
|
||||
* Compressed image file parameters and helper routines
|
||||
*/
|
||||
#define NMATCH 3 /* shortest match possible */
|
||||
#define NRUN (NMATCH+31) /* longest match possible */
|
||||
#define NMEM 1024 /* window size */
|
||||
#define NDUMP 128 /* maximum length of dump */
|
||||
#define NCBLOCK 6000 /* size of compressed blocks */
|
||||
extern void _twiddlecompressed(uchar*, int);
|
||||
extern int _compblocksize(Rectangle, int);
|
||||
|
||||
/* XXX backwards helps; should go */
|
||||
extern int log2[];
|
||||
extern u32int drawld2chan[];
|
||||
extern void drawsetdebug(int);
|
||||
|
||||
/*
|
||||
* Port magic.
|
||||
*/
|
||||
int _drawmsgread(Display*, void*, int);
|
||||
int _drawmsgwrite(Display*, void*, int);
|
||||
63
include/event.h
Normal file
63
include/event.h
Normal file
@@ -0,0 +1,63 @@
|
||||
typedef struct Event Event;
|
||||
typedef struct Menu Menu;
|
||||
|
||||
enum
|
||||
{
|
||||
Emouse = 1,
|
||||
Ekeyboard = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MAXSLAVE = 32,
|
||||
EMAXMSG = 128+8192, /* size of 9p header+data */
|
||||
};
|
||||
|
||||
struct Mouse
|
||||
{
|
||||
int buttons; /* bit array: LMR=124 */
|
||||
Point xy;
|
||||
ulong msec;
|
||||
};
|
||||
|
||||
struct Event
|
||||
{
|
||||
int kbdc;
|
||||
Mouse mouse;
|
||||
int n; /* number of characters in message */
|
||||
void *v; /* data unpacked by general event-handling function */
|
||||
uchar data[EMAXMSG]; /* message from an arbitrary file descriptor */
|
||||
};
|
||||
|
||||
struct Menu
|
||||
{
|
||||
char **item;
|
||||
char *(*gen)(int);
|
||||
int lasthit;
|
||||
};
|
||||
|
||||
/*
|
||||
* Events
|
||||
*/
|
||||
extern void einit(ulong);
|
||||
extern ulong estart(ulong, int, int);
|
||||
extern ulong estartfn(ulong, int, int, int (*fn)(int, Event*, uchar*, int));
|
||||
extern ulong etimer(ulong, int);
|
||||
extern ulong event(Event*);
|
||||
extern ulong eread(ulong, Event*);
|
||||
extern Mouse emouse(void);
|
||||
extern int ekbd(void);
|
||||
extern int ecanread(ulong);
|
||||
extern int ecanmouse(void);
|
||||
extern int ecankbd(void);
|
||||
extern void eresized(int); /* supplied by user */
|
||||
extern int emenuhit(int, Mouse*, Menu*);
|
||||
extern int eatomouse(Mouse*, char*, int);
|
||||
extern Rectangle getrect(int, Mouse*);
|
||||
struct Cursor;
|
||||
extern void esetcursor(struct Cursor*);
|
||||
extern void emoveto(Point);
|
||||
extern Rectangle egetrect(int, Mouse*);
|
||||
extern void edrawgetrect(Rectangle, int);
|
||||
extern int ereadmouse(Mouse*);
|
||||
extern int eatomouse(Mouse*, char*, int);
|
||||
100
include/fmt.h
Normal file
100
include/fmt.h
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FMTH_
|
||||
#define _FMTH_ 1
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef _UTFH_
|
||||
#include <utf.h>
|
||||
#endif
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
enum{
|
||||
FmtWidth = 1,
|
||||
FmtLeft = FmtWidth << 1,
|
||||
FmtPrec = FmtLeft << 1,
|
||||
FmtSharp = FmtPrec << 1,
|
||||
FmtSpace = FmtSharp << 1,
|
||||
FmtSign = FmtSpace << 1,
|
||||
FmtZero = FmtSign << 1,
|
||||
FmtUnsigned = FmtZero << 1,
|
||||
FmtShort = FmtUnsigned << 1,
|
||||
FmtLong = FmtShort << 1,
|
||||
FmtVLong = FmtLong << 1,
|
||||
FmtComma = FmtVLong << 1,
|
||||
FmtByte = FmtComma << 1,
|
||||
FmtLDouble = FmtByte << 1,
|
||||
|
||||
FmtFlag = FmtLDouble << 1
|
||||
};
|
||||
|
||||
extern int print(char*, ...);
|
||||
extern char* seprint(char*, char*, char*, ...);
|
||||
extern char* vseprint(char*, char*, char*, va_list);
|
||||
extern int snprint(char*, int, char*, ...);
|
||||
extern int vsnprint(char*, int, char*, va_list);
|
||||
extern char* smprint(char*, ...);
|
||||
extern char* vsmprint(char*, va_list);
|
||||
extern int sprint(char*, char*, ...);
|
||||
extern int fprint(int, char*, ...);
|
||||
extern int vfprint(int, char*, va_list);
|
||||
|
||||
extern int runesprint(Rune*, char*, ...);
|
||||
extern int runesnprint(Rune*, int, char*, ...);
|
||||
extern int runevsnprint(Rune*, int, char*, va_list);
|
||||
extern Rune* runeseprint(Rune*, Rune*, char*, ...);
|
||||
extern Rune* runevseprint(Rune*, Rune*, char*, va_list);
|
||||
extern Rune* runesmprint(char*, ...);
|
||||
extern Rune* runevsmprint(char*, va_list);
|
||||
|
||||
extern int fmtfdinit(Fmt*, int, char*, int);
|
||||
extern int fmtfdflush(Fmt*);
|
||||
extern int fmtstrinit(Fmt*);
|
||||
extern char* fmtstrflush(Fmt*);
|
||||
extern int runefmtstrinit(Fmt*);
|
||||
|
||||
extern int quotestrfmt(Fmt *f);
|
||||
extern void quotefmtinstall(void);
|
||||
extern int (*fmtdoquote)(int);
|
||||
|
||||
|
||||
extern int fmtinstall(int, int (*)(Fmt*));
|
||||
extern int dofmt(Fmt*, char*);
|
||||
extern int fmtprint(Fmt*, char*, ...);
|
||||
extern int fmtvprint(Fmt*, char*, va_list);
|
||||
extern int fmtrune(Fmt*, int);
|
||||
extern int fmtstrcpy(Fmt*, char*);
|
||||
|
||||
extern double fmtstrtod(const char *, char **);
|
||||
extern double fmtcharstod(int(*)(void*), void*);
|
||||
|
||||
#endif
|
||||
85
include/frame.h
Normal file
85
include/frame.h
Normal file
@@ -0,0 +1,85 @@
|
||||
typedef struct Frbox Frbox;
|
||||
typedef struct Frame Frame;
|
||||
|
||||
enum{
|
||||
BACK,
|
||||
HIGH,
|
||||
BORD,
|
||||
TEXT,
|
||||
HTEXT,
|
||||
NCOL
|
||||
};
|
||||
|
||||
#define FRTICKW 3
|
||||
|
||||
struct Frbox
|
||||
{
|
||||
long wid; /* in pixels */
|
||||
long nrune; /* <0 ==> negate and treat as break char */
|
||||
uchar *ptr;
|
||||
short bc; /* break char */
|
||||
short minwid;
|
||||
};
|
||||
|
||||
struct Frame
|
||||
{
|
||||
Font *font; /* of chars in the frame */
|
||||
Display *display; /* on which frame appears */
|
||||
Image *b; /* on which frame appears */
|
||||
Image *cols[NCOL]; /* text and background colors */
|
||||
Rectangle r; /* in which text appears */
|
||||
Rectangle entire; /* of full frame */
|
||||
void (*scroll)(Frame*, int); /* scroll function provided by application */
|
||||
Frbox *box;
|
||||
ulong p0, p1; /* selection */
|
||||
ushort nbox, nalloc;
|
||||
ushort maxtab; /* max size of tab, in pixels */
|
||||
ushort nchars; /* # runes in frame */
|
||||
ushort nlines; /* # lines with text */
|
||||
ushort maxlines; /* total # lines in frame */
|
||||
ushort lastlinefull; /* last line fills frame */
|
||||
ushort modified; /* changed since frselect() */
|
||||
Image *tick; /* typing tick */
|
||||
Image *tickback; /* saved image under tick */
|
||||
int ticked; /* flag: is tick onscreen? */
|
||||
};
|
||||
|
||||
ulong frcharofpt(Frame*, Point);
|
||||
Point frptofchar(Frame*, ulong);
|
||||
int frdelete(Frame*, ulong, ulong);
|
||||
void frinsert(Frame*, Rune*, Rune*, ulong);
|
||||
void frselect(Frame*, Mousectl*);
|
||||
void frselectpaint(Frame*, Point, Point, Image*);
|
||||
void frdrawsel(Frame*, Point, ulong, ulong, int);
|
||||
void frdrawsel0(Frame*, Point, ulong, ulong, Image*, Image*);
|
||||
void frinit(Frame*, Rectangle, Font*, Image*, Image**);
|
||||
void frsetrects(Frame*, Rectangle, Image*);
|
||||
void frclear(Frame*, int);
|
||||
|
||||
uchar *_frallocstr(Frame*, unsigned);
|
||||
void _frinsure(Frame*, int, unsigned);
|
||||
Point _frdraw(Frame*, Point);
|
||||
void _frgrowbox(Frame*, int);
|
||||
void _frfreebox(Frame*, int, int);
|
||||
void _frmergebox(Frame*, int);
|
||||
void _frdelbox(Frame*, int, int);
|
||||
void _frsplitbox(Frame*, int, int);
|
||||
int _frfindbox(Frame*, int, ulong, ulong);
|
||||
void _frclosebox(Frame*, int, int);
|
||||
int _frcanfit(Frame*, Point, Frbox*);
|
||||
void _frcklinewrap(Frame*, Point*, Frbox*);
|
||||
void _frcklinewrap0(Frame*, Point*, Frbox*);
|
||||
void _fradvance(Frame*, Point*, Frbox*);
|
||||
int _frnewwid(Frame*, Point, Frbox*);
|
||||
int _frnewwid0(Frame*, Point, Frbox*);
|
||||
void _frclean(Frame*, Point, int, int);
|
||||
void _frredraw(Frame*, Point);
|
||||
void _fraddbox(Frame*, int, int);
|
||||
Point _frptofcharptb(Frame*, ulong, Point, int);
|
||||
Point _frptofcharnb(Frame*, ulong, int);
|
||||
int _frstrlen(Frame*, int);
|
||||
void frtick(Frame*, Point, int);
|
||||
void frinittick(Frame*);
|
||||
|
||||
#define NRUNE(b) ((b)->nrune<0? 1 : (b)->nrune)
|
||||
#define NBYTE(b) strlen((char*)(b)->ptr)
|
||||
36
include/keyboard.h
Normal file
36
include/keyboard.h
Normal file
@@ -0,0 +1,36 @@
|
||||
typedef struct Keyboardctl Keyboardctl;
|
||||
|
||||
struct Keyboardctl
|
||||
{
|
||||
struct Channel *c; /* chan(Rune)[20] */
|
||||
|
||||
char *file;
|
||||
int consfd; /* to cons file */
|
||||
int ctlfd; /* to ctl file */
|
||||
int pid; /* of slave proc */
|
||||
};
|
||||
|
||||
|
||||
extern Keyboardctl* initkeyboard(char*);
|
||||
extern int ctlkeyboard(Keyboardctl*, char*);
|
||||
extern void closekeyboard(Keyboardctl*);
|
||||
|
||||
enum {
|
||||
KF= 0xF000, /* Rune: beginning of private Unicode space */
|
||||
/* KF|1, KF|2, ..., KF|0xC is F1, F2, ..., F12 */
|
||||
Khome= KF|0x0D,
|
||||
Kup= KF|0x0E,
|
||||
Kpgup= KF|0x0F,
|
||||
Kprint= KF|0x10,
|
||||
Kleft= KF|0x11,
|
||||
Kright= KF|0x12,
|
||||
Kdown= 0x80,
|
||||
Kview= 0x80,
|
||||
Kpgdown= KF|0x13,
|
||||
Kins= KF|0x14,
|
||||
Kend= '\r', /* [sic] */
|
||||
|
||||
Kalt= KF|0x15,
|
||||
Kshift= KF|0x16,
|
||||
Kctl= KF|0x17,
|
||||
};
|
||||
254
include/lib9.h
Normal file
254
include/lib9.h
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* 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 _LIB9H_
|
||||
#define _LIB9H_ 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifndef _FMTH_
|
||||
# include <fmt.h>
|
||||
#endif
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
#define _NEEDUCHAR 1
|
||||
#define _NEEDUSHORT 1
|
||||
#define _NEEDUINT 1
|
||||
#define _NEEDULONG 1
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/types.h>
|
||||
# if defined(__USE_MISC)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# if !defined(_POSIX_SOURCE)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef signed char schar;
|
||||
typedef unsigned int u32int;
|
||||
#ifdef _NEEDUCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#ifdef _NEEDUSHORT
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
#ifdef _NEEDUINT
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#ifdef _NEEDULONG
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long long vlong;
|
||||
|
||||
/* rfork to create new process running fn(arg) */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef RFFDG
|
||||
#undef RFNOTEG
|
||||
#undef RFPROC
|
||||
#undef RFMEM
|
||||
#undef RFNOWAIT
|
||||
#undef RFCFDG
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/* RFNAMEG = (1<<0), */
|
||||
/* RFENVG = (1<<1), */
|
||||
RFFDG = (1<<2),
|
||||
RFNOTEG = (1<<3),
|
||||
RFPROC = (1<<4),
|
||||
RFMEM = (1<<5),
|
||||
RFNOWAIT = (1<<6),
|
||||
/* RFCNAMEG = (1<<10), */
|
||||
/* RFCENVG = (1<<11), */
|
||||
RFCFDG = (1<<12),
|
||||
/* RFREND = (1<<13), */
|
||||
/* RFNOMNT = (1<<14) */
|
||||
};
|
||||
extern int ffork(int, void(*)(void*), void*);
|
||||
|
||||
/* wait for processes */
|
||||
#define wait _p9wait
|
||||
typedef struct Waitmsg Waitmsg;
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
};
|
||||
extern int await(char*, int);
|
||||
extern Waitmsg* wait(void);
|
||||
|
||||
/* synchronization */
|
||||
typedef struct Lock Lock;
|
||||
struct Lock
|
||||
{
|
||||
int val;
|
||||
};
|
||||
|
||||
extern int _tas(void*);
|
||||
extern void lock(Lock*);
|
||||
extern void unlock(Lock*);
|
||||
extern int canlock(Lock*);
|
||||
|
||||
typedef struct QLp QLp;
|
||||
struct QLp
|
||||
{
|
||||
int inuse;
|
||||
QLp *next;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef struct QLock QLock;
|
||||
struct QLock
|
||||
{
|
||||
Lock lock;
|
||||
int locked;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void qlock(QLock*);
|
||||
extern void qunlock(QLock*);
|
||||
extern int canqlock(QLock*);
|
||||
extern void _qlockinit(ulong (*)(ulong, ulong));
|
||||
|
||||
typedef struct RWLock RWLock;
|
||||
struct RWLock
|
||||
{
|
||||
Lock lock;
|
||||
int readers;
|
||||
int writer;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rlock(RWLock*);
|
||||
extern void runlock(RWLock*);
|
||||
extern int canrlock(RWLock*);
|
||||
extern void wlock(RWLock*);
|
||||
extern void wunlock(RWLock*);
|
||||
extern int canwlock(RWLock*);
|
||||
|
||||
typedef struct Rendez Rendez;
|
||||
struct Rendez
|
||||
{
|
||||
QLock *l;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rsleep(Rendez*);
|
||||
extern int rwakeup(Rendez*);
|
||||
extern int rwakeupall(Rendez*);
|
||||
|
||||
extern ulong rendezvous(ulong, ulong);
|
||||
|
||||
/* one of a kind */
|
||||
extern void sysfatal(char*, ...);
|
||||
extern int nrand(int);
|
||||
extern void setmalloctag(void*, ulong);
|
||||
extern void setrealloctag(void*, ulong);
|
||||
extern void *mallocz(ulong, int);
|
||||
extern long readn(int, void*, long);
|
||||
extern void exits(char*);
|
||||
extern void _exits(char*);
|
||||
extern ulong getcallerpc(void*);
|
||||
|
||||
/* string routines */
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
extern int cistrncmp(char*, char*, int);
|
||||
extern int cistrcmp(char*, char*);
|
||||
extern char* cistrstr(char*, char*);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
extern int gettokens(char *, char **, int, char *);
|
||||
|
||||
/* formatting helpers */
|
||||
extern int dec64(uchar*, int, char*, int);
|
||||
extern int enc64(char*, int, uchar*, int);
|
||||
extern int dec32(uchar*, int, char*, int);
|
||||
extern int enc32(char*, int, uchar*, int);
|
||||
extern int dec16(uchar*, int, char*, int);
|
||||
extern int enc16(char*, int, uchar*, int);
|
||||
extern int encodefmt(Fmt*);
|
||||
|
||||
/* error string */
|
||||
enum
|
||||
{
|
||||
ERRMAX = 128
|
||||
};
|
||||
extern void rerrstr(char*, uint);
|
||||
extern void werrstr(char*, ...);
|
||||
extern int errstr(char*, uint);
|
||||
|
||||
/* compiler directives on plan 9 */
|
||||
#define USED(x) if(x){}else{}
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
/* command line */
|
||||
extern char *argv0;
|
||||
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
|
||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
||||
argc--, argv++) {\
|
||||
char *_args, *_argt;\
|
||||
Rune _argc;\
|
||||
_args = &argv[0][1];\
|
||||
if(_args[0]=='-' && _args[1]==0){\
|
||||
argc--; argv++; break;\
|
||||
}\
|
||||
_argc = 0;\
|
||||
while(*_args && (_args += chartorune(&_argc, _args)))\
|
||||
switch(_argc)
|
||||
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
|
||||
#define ARGF() (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
|
||||
#define EARGF(x) (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
|
||||
|
||||
#define ARGC() _argc
|
||||
|
||||
#define OREAD O_RDONLY
|
||||
#define OWRITE O_WRONLY
|
||||
#define AEXIST 0
|
||||
#define AREAD 4
|
||||
#define AWRITE 2
|
||||
#define AEXEC 1
|
||||
#define ORCLOSE 8
|
||||
#define OCEXEC 16
|
||||
|
||||
#define dup dup2
|
||||
#define exec execv
|
||||
#define seek lseek
|
||||
#define getwd getcwd
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIB9H_ */
|
||||
2
include/libc.h
Normal file
2
include/libc.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#include <lib9.h>
|
||||
|
||||
44
include/mouse.h
Normal file
44
include/mouse.h
Normal file
@@ -0,0 +1,44 @@
|
||||
typedef struct Menu Menu;
|
||||
typedef struct Mousectl Mousectl;
|
||||
|
||||
struct Mouse
|
||||
{
|
||||
int buttons; /* bit array: LMR=124 */
|
||||
Point xy;
|
||||
ulong msec;
|
||||
};
|
||||
|
||||
struct Mousectl
|
||||
{
|
||||
Mouse m;
|
||||
struct Channel *c; /* chan(Mouse) */
|
||||
struct Channel *resizec; /* chan(int)[2] */
|
||||
/* buffered in case client is waiting for a mouse action before handling resize */
|
||||
|
||||
char *file;
|
||||
int mfd; /* to mouse file */
|
||||
int cfd; /* to cursor file */
|
||||
int pid; /* of slave proc */
|
||||
Display *display;
|
||||
/*Image* image; / * of associated window/display */
|
||||
};
|
||||
|
||||
struct Menu
|
||||
{
|
||||
char **item;
|
||||
char *(*gen)(int);
|
||||
int lasthit;
|
||||
};
|
||||
|
||||
/*
|
||||
* Mouse
|
||||
*/
|
||||
extern Mousectl* initmouse(char*, Image*);
|
||||
extern void moveto(Mousectl*, Point);
|
||||
extern int readmouse(Mousectl*);
|
||||
extern void closemouse(Mousectl*);
|
||||
struct Cursor;
|
||||
extern void setcursor(Mousectl*, struct Cursor*);
|
||||
extern void drawgetrect(Rectangle, int);
|
||||
extern Rectangle getrect(int, Mousectl*);
|
||||
extern int menuhit(int, Mousectl*, Menu*, Screen*);
|
||||
71
include/regexp9.h
Normal file
71
include/regexp9.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef _REGEXP9H_
|
||||
|
||||
#define _REGEXP9H_ 1
|
||||
#include <utf.h>
|
||||
|
||||
typedef struct Resub Resub;
|
||||
typedef struct Reclass Reclass;
|
||||
typedef struct Reinst Reinst;
|
||||
typedef struct Reprog Reprog;
|
||||
|
||||
/*
|
||||
* Sub expression matches
|
||||
*/
|
||||
struct Resub{
|
||||
union
|
||||
{
|
||||
char *sp;
|
||||
Rune *rsp;
|
||||
}s;
|
||||
union
|
||||
{
|
||||
char *ep;
|
||||
Rune *rep;
|
||||
}e;
|
||||
};
|
||||
|
||||
/*
|
||||
* character class, each pair of rune's defines a range
|
||||
*/
|
||||
struct Reclass{
|
||||
Rune *end;
|
||||
Rune spans[64];
|
||||
};
|
||||
|
||||
/*
|
||||
* Machine instructions
|
||||
*/
|
||||
struct Reinst{
|
||||
int type;
|
||||
union {
|
||||
Reclass *cp; /* class pointer */
|
||||
Rune r; /* character */
|
||||
int subid; /* sub-expression id for RBRA and LBRA */
|
||||
Reinst *right; /* right child of OR */
|
||||
}u1;
|
||||
union { /* regexp relies on these two being in the same union */
|
||||
Reinst *left; /* left child of OR */
|
||||
Reinst *next; /* next instruction for CAT & LBRA */
|
||||
}u2;
|
||||
};
|
||||
|
||||
/*
|
||||
* Reprogram definition
|
||||
*/
|
||||
struct Reprog{
|
||||
Reinst *startinst; /* start pc */
|
||||
Reclass class[16]; /* .data */
|
||||
Reinst firstinst[5]; /* .text */
|
||||
};
|
||||
|
||||
extern Reprog *regcomp(char*);
|
||||
extern Reprog *regcomplit(char*);
|
||||
extern Reprog *regcompnl(char*);
|
||||
extern void regerror(char*);
|
||||
extern int regexec(Reprog*, char*, Resub*, int);
|
||||
extern void regsub(char*, char*, int, Resub*, int);
|
||||
|
||||
extern int rregexec(Reprog*, Rune*, Resub*, int);
|
||||
extern void rregsub(Rune*, Rune*, Resub*, int);
|
||||
|
||||
#endif
|
||||
132
include/thread.h
Normal file
132
include/thread.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#ifndef _THREADH_
|
||||
#define _THREADH_ 1
|
||||
|
||||
/* avoid conflicts with socket library */
|
||||
#undef send
|
||||
#define send _threadsend
|
||||
#undef recv
|
||||
#define recv _threadrecv
|
||||
|
||||
typedef struct Alt Alt;
|
||||
typedef struct Channel Channel;
|
||||
typedef struct Ref Ref;
|
||||
|
||||
/* Channel structure. S is the size of the buffer. For unbuffered channels
|
||||
* s is zero. v is an array of s values. If s is zero, v is unused.
|
||||
* f and n represent the state of the queue pointed to by v.
|
||||
*/
|
||||
|
||||
enum {
|
||||
Nqwds = 2,
|
||||
Nqshift = 5, // 2log #of bits in long
|
||||
Nqmask = - 1,
|
||||
Nqbits = (1 << Nqshift) * 2,
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
int s; // Size of the channel (may be zero)
|
||||
unsigned int f; // Extraction point (insertion pt: (f + n) % s)
|
||||
unsigned int n; // Number of values in the channel
|
||||
int e; // Element size
|
||||
int freed; // Set when channel is being deleted
|
||||
volatile Alt **qentry; // Receivers/senders waiting (malloc)
|
||||
volatile int nentry; // # of entries malloc-ed
|
||||
unsigned char v[1]; // Array of s values in the channel
|
||||
};
|
||||
|
||||
|
||||
/* Channel operations for alt: */
|
||||
typedef enum {
|
||||
CHANEND,
|
||||
CHANSND,
|
||||
CHANRCV,
|
||||
CHANNOP,
|
||||
CHANNOBLK,
|
||||
} ChanOp;
|
||||
|
||||
struct Alt {
|
||||
Channel *c; /* channel */
|
||||
void *v; /* pointer to value */
|
||||
ChanOp op; /* operation */
|
||||
|
||||
/* the next variables are used internally to alt
|
||||
* they need not be initialized
|
||||
*/
|
||||
Channel **tag; /* pointer to rendez-vous tag */
|
||||
int entryno; /* entry number */
|
||||
};
|
||||
|
||||
struct Ref {
|
||||
long ref;
|
||||
};
|
||||
|
||||
int alt(Alt alts[]);
|
||||
Channel* chancreate(int elemsize, int bufsize);
|
||||
int chaninit(Channel *c, int elemsize, int elemcnt);
|
||||
void chanfree(Channel *c);
|
||||
int chanprint(Channel *, char *, ...);
|
||||
long decref(Ref *r); /* returns 0 iff value is now zero */
|
||||
void incref(Ref *r);
|
||||
int nbrecv(Channel *c, void *v);
|
||||
void* nbrecvp(Channel *c);
|
||||
unsigned long nbrecvul(Channel *c);
|
||||
int nbsend(Channel *c, void *v);
|
||||
int nbsendp(Channel *c, void *v);
|
||||
int nbsendul(Channel *c, unsigned long v);
|
||||
int proccreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
|
||||
int procrfork(void (*f)(void *arg), void *arg, unsigned int stacksize, int flag);
|
||||
void** procdata(void);
|
||||
void procexec(Channel *, char *, char *[]);
|
||||
void procexecl(Channel *, char *, ...);
|
||||
int recv(Channel *c, void *v);
|
||||
void* recvp(Channel *c);
|
||||
unsigned long recvul(Channel *c);
|
||||
int send(Channel *c, void *v);
|
||||
int sendp(Channel *c, void *v);
|
||||
int sendul(Channel *c, unsigned long v);
|
||||
int threadcreate(void (*f)(void *arg), void *arg, unsigned int stacksize);
|
||||
void** threaddata(void);
|
||||
void threadexits(char *);
|
||||
void threadexitsall(char *);
|
||||
int threadgetgrp(void); /* return thread group of current thread */
|
||||
char* threadgetname(void);
|
||||
void threadint(int); /* interrupt thread */
|
||||
void threadintgrp(int); /* interrupt threads in grp */
|
||||
void threadkill(int); /* kill thread */
|
||||
void threadkillgrp(int); /* kill threads in group */
|
||||
void threadmain(int argc, char *argv[]);
|
||||
void threadnonotes(void);
|
||||
int threadnotify(int (*f)(void*, char*), int in);
|
||||
int threadid(void);
|
||||
int threadpid(int);
|
||||
int threadsetgrp(int); /* set thread group, return old */
|
||||
void threadsetname(char *name);
|
||||
Channel* threadwaitchan(void);
|
||||
int tprivalloc(void);
|
||||
void tprivfree(int);
|
||||
void **tprivaddr(int);
|
||||
void yield(void);
|
||||
|
||||
long threadstack(void);
|
||||
|
||||
extern int mainstacksize;
|
||||
|
||||
/* slave I/O processes */
|
||||
typedef struct Ioproc Ioproc;
|
||||
|
||||
Ioproc* ioproc(void);
|
||||
void closeioproc(Ioproc*);
|
||||
void iointerrupt(Ioproc*);
|
||||
|
||||
int ioclose(Ioproc*, int);
|
||||
int iodial(Ioproc*, char*, char*, char*, int*);
|
||||
int ioopen(Ioproc*, char*, int);
|
||||
long ioread(Ioproc*, int, void*, long);
|
||||
long ioreadn(Ioproc*, int, void*, long);
|
||||
long iowrite(Ioproc*, int, void*, long);
|
||||
int iosleep(Ioproc*, long);
|
||||
|
||||
long iocall(Ioproc*, long (*)(va_list*), ...);
|
||||
void ioret(Ioproc*, int);
|
||||
|
||||
#endif /* _THREADH_ */
|
||||
0
include/u.h
Normal file
0
include/u.h
Normal file
51
include/utf.h
Normal file
51
include/utf.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef _UTFH_
|
||||
#define _UTFH_ 1
|
||||
|
||||
typedef unsigned short Rune; /* 16 bits */
|
||||
|
||||
enum
|
||||
{
|
||||
UTFmax = 3, /* maximum bytes per rune */
|
||||
Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
|
||||
Runeself = 0x80, /* rune and UTF sequences are the same (<) */
|
||||
Runeerror = 0x80, /* decoding error in UTF */
|
||||
};
|
||||
|
||||
/*
|
||||
* rune routines
|
||||
*/
|
||||
extern int runetochar(char*, Rune*);
|
||||
extern int chartorune(Rune*, char*);
|
||||
extern int runelen(long);
|
||||
extern int runenlen(Rune*, int);
|
||||
extern int fullrune(char*, int);
|
||||
extern int utflen(char*);
|
||||
extern int utfnlen(char*, long);
|
||||
extern char* utfrune(char*, long);
|
||||
extern char* utfrrune(char*, long);
|
||||
extern char* utfutf(char*, char*);
|
||||
extern char* utfecpy(char*, char*, char*);
|
||||
|
||||
extern Rune* runestrcat(Rune*, Rune*);
|
||||
extern Rune* runestrchr(Rune*, Rune);
|
||||
extern int runestrcmp(Rune*, Rune*);
|
||||
extern Rune* runestrcpy(Rune*, Rune*);
|
||||
extern Rune* runestrncpy(Rune*, Rune*, long);
|
||||
extern Rune* runestrecpy(Rune*, Rune*, Rune*);
|
||||
extern Rune* runestrdup(Rune*);
|
||||
extern Rune* runestrncat(Rune*, Rune*, long);
|
||||
extern int runestrncmp(Rune*, Rune*, long);
|
||||
extern Rune* runestrrchr(Rune*, Rune);
|
||||
extern long runestrlen(Rune*);
|
||||
extern Rune* runestrstr(Rune*, Rune*);
|
||||
|
||||
extern Rune tolowerrune(Rune);
|
||||
extern Rune totitlerune(Rune);
|
||||
extern Rune toupperrune(Rune);
|
||||
extern int isalpharune(Rune);
|
||||
extern int islowerrune(Rune);
|
||||
extern int isspacerune(Rune);
|
||||
extern int istitlerune(Rune);
|
||||
extern int isupperrune(Rune);
|
||||
|
||||
#endif
|
||||
336
man/man3/bio.3
Normal file
336
man/man3/bio.3
Normal file
@@ -0,0 +1,336 @@
|
||||
.TH BIO 3
|
||||
.SH NAME
|
||||
Bopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetd, Bungetc, Bread, Bseek, Boffset, Bfildes, Blinelen, Bputc, Bprint, Bvprint, Bwrite, Bflush, Bterm, Bbuffered \- buffered input/output
|
||||
.SH SYNOPSIS
|
||||
.ta \w'Biobuf* 'u
|
||||
.B #include <fmt.h>
|
||||
.B #include <bio.h>
|
||||
.PP
|
||||
.B
|
||||
Biobuf* Bopen(char *file, int mode)
|
||||
.PP
|
||||
.B
|
||||
int Binit(Biobuf *bp, int fd, int mode)
|
||||
.PP
|
||||
.B
|
||||
int Bterm(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bprint(Biobuf *bp, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int Bvprint(Biobuf *bp, char *format, va_list arglist);
|
||||
.PP
|
||||
.B
|
||||
void* Brdline(Biobuf *bp, int delim)
|
||||
.PP
|
||||
.B
|
||||
char* Brdstr(Biobuf *bp, int delim, int nulldelim)
|
||||
.PP
|
||||
.B
|
||||
int Blinelen(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
off_t Boffset(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bfildes(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bgetc(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
long Bgetrune(Biobufhdr *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bgetd(Biobuf *bp, double *d)
|
||||
.PP
|
||||
.B
|
||||
int Bungetc(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bungetrune(Biobufhdr *bp)
|
||||
.PP
|
||||
.B
|
||||
off_t Bseek(Biobuf *bp, off_t n, int type)
|
||||
.PP
|
||||
.B
|
||||
int Bputc(Biobuf *bp, int c)
|
||||
.PP
|
||||
.B
|
||||
int Bputrune(Biobufhdr *bp, long c)
|
||||
.PP
|
||||
.B
|
||||
long Bread(Biobuf *bp, void *addr, long nbytes)
|
||||
.PP
|
||||
.B
|
||||
long Bwrite(Biobuf *bp, void *addr, long nbytes)
|
||||
.PP
|
||||
.B
|
||||
int Bflush(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bbuffered(Biobuf *bp)
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
These routines implement fast buffered I/O.
|
||||
I/O on different file descriptors is independent.
|
||||
.PP
|
||||
.I Bopen
|
||||
opens
|
||||
.I file
|
||||
for mode
|
||||
.B O_RDONLY
|
||||
or creates for mode
|
||||
.BR O_WRONLY .
|
||||
It calls
|
||||
.IR malloc (3)
|
||||
to allocate a buffer.
|
||||
.PP
|
||||
.I Binit
|
||||
initializes a buffer
|
||||
with the open file descriptor passed in
|
||||
by the user.
|
||||
.PP
|
||||
Arguments
|
||||
of types pointer to Biobuf and pointer to Biobuf
|
||||
can be used interchangeably in the following routines.
|
||||
.PP
|
||||
.IR Bopen ,
|
||||
.IR Binit ,
|
||||
or
|
||||
.I Binits
|
||||
should be called before any of the
|
||||
other routines on that buffer.
|
||||
.I Bfildes
|
||||
returns the integer file descriptor of the associated open file.
|
||||
.PP
|
||||
.I Bterm
|
||||
flushes the buffer for
|
||||
.IR bp .
|
||||
If the buffer was allocated by
|
||||
.IR Bopen ,
|
||||
the buffer is
|
||||
.I freed
|
||||
and the file is closed.
|
||||
.PP
|
||||
.I Brdline
|
||||
reads a string from the file associated with
|
||||
.I bp
|
||||
up to and including the first
|
||||
.I delim
|
||||
character.
|
||||
The delimiter character at the end of the line is
|
||||
not altered.
|
||||
.I Brdline
|
||||
returns a pointer to the start of the line or
|
||||
.L 0
|
||||
on end-of-file or read error.
|
||||
.I Blinelen
|
||||
returns the length (including the delimiter)
|
||||
of the most recent string returned by
|
||||
.IR Brdline .
|
||||
.PP
|
||||
.I Brdstr
|
||||
returns a
|
||||
.IR malloc (3)-allocated
|
||||
buffer containing the next line of input delimited by
|
||||
.IR delim ,
|
||||
terminated by a NUL (0) byte.
|
||||
Unlike
|
||||
.IR Brdline ,
|
||||
which returns when its buffer is full even if no delimiter has been found,
|
||||
.I Brdstr
|
||||
will return an arbitrarily long line in a single call.
|
||||
If
|
||||
.I nulldelim
|
||||
is set, the terminal delimiter will be overwritten with a NUL.
|
||||
After a successful call to
|
||||
.IR Brdstr ,
|
||||
the return value of
|
||||
.I Blinelen
|
||||
will be the length of the returned buffer, excluding the NUL.
|
||||
.PP
|
||||
.I Bgetc
|
||||
returns the next byte from
|
||||
.IR bp ,
|
||||
or a negative value
|
||||
at end of file.
|
||||
.I Bungetc
|
||||
may be called immediately after
|
||||
.I Bgetc
|
||||
to allow the same byte to be reread.
|
||||
.PP
|
||||
.I Bgetrune
|
||||
calls
|
||||
.I Bgetc
|
||||
to read the bytes of the next
|
||||
.SM UTF
|
||||
sequence in the input stream and returns the value of the rune
|
||||
represented by the sequence.
|
||||
It returns a negative value
|
||||
at end of file.
|
||||
.I Bungetrune
|
||||
may be called immediately after
|
||||
.I Bgetrune
|
||||
to allow the same
|
||||
.SM UTF
|
||||
sequence to be reread as either bytes or a rune.
|
||||
.I Bungetc
|
||||
and
|
||||
.I Bungetrune
|
||||
may back up a maximum of five bytes.
|
||||
.PP
|
||||
.I Bgetd
|
||||
uses
|
||||
.I fmtcharstod
|
||||
(undocumented)
|
||||
and
|
||||
.I Bgetc
|
||||
to read the formatted
|
||||
floating-point number in the input stream,
|
||||
skipping initial blanks and tabs.
|
||||
The value is stored in
|
||||
.BR *d.
|
||||
.PP
|
||||
.I Bread
|
||||
reads
|
||||
.I nbytes
|
||||
of data from
|
||||
.I bp
|
||||
into memory starting at
|
||||
.IR addr .
|
||||
The number of bytes read is returned on success
|
||||
and a negative value is returned if a read error occurred.
|
||||
.PP
|
||||
.I Bseek
|
||||
applies
|
||||
.IR lseek (2)
|
||||
to
|
||||
.IR bp .
|
||||
It returns the new file offset.
|
||||
.I Boffset
|
||||
returns the file offset of the next character to be processed.
|
||||
.PP
|
||||
.I Bputc
|
||||
outputs the low order 8 bits of
|
||||
.I c
|
||||
on
|
||||
.IR bp .
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value is returned.
|
||||
Otherwise, a zero is returned.
|
||||
.PP
|
||||
.I Bputrune
|
||||
calls
|
||||
.I Bputc
|
||||
to output the low order
|
||||
16 bits of
|
||||
.I c
|
||||
as a rune
|
||||
in
|
||||
.SM UTF
|
||||
format
|
||||
on the output stream.
|
||||
.PP
|
||||
.I Bprint
|
||||
is a buffered interface to
|
||||
.IR print (2).
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value
|
||||
.RB ( Beof )
|
||||
is returned.
|
||||
Otherwise, the number of bytes output is returned.
|
||||
.I Bvprint
|
||||
does the same except it takes as argument a
|
||||
.B va_list
|
||||
parameter, so it can be called within a variadic function.
|
||||
.PP
|
||||
.I Bwrite
|
||||
outputs
|
||||
.I nbytes
|
||||
of data starting at
|
||||
.I addr
|
||||
to
|
||||
.IR bp .
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value is returned.
|
||||
Otherwise, the number of bytes written is returned.
|
||||
.PP
|
||||
.I Bflush
|
||||
causes any buffered output associated with
|
||||
.I bp
|
||||
to be written.
|
||||
The return is as for
|
||||
.IR Bputc .
|
||||
.I Bflush
|
||||
is called on
|
||||
exit for every buffer still open
|
||||
for writing.
|
||||
.PP
|
||||
.I Bbuffered
|
||||
returns the number of bytes in the buffer.
|
||||
When reading, this is the number of bytes still available from the last
|
||||
read on the file; when writing, it is the number of bytes ready to be
|
||||
written.
|
||||
.PP
|
||||
This library uses
|
||||
.IR fmt (3)
|
||||
for diagnostic messages about internal errors,
|
||||
as well as for the implementation of
|
||||
.I Bprint
|
||||
and
|
||||
.IR Bvprint .
|
||||
It uses
|
||||
.IR utf (3)
|
||||
for the implementation of
|
||||
.I Bgetrune
|
||||
and
|
||||
.IR Bputrune .
|
||||
.SH SEE ALSO
|
||||
.IR atexit (3).
|
||||
.IR open (2),
|
||||
.IR print (3),
|
||||
.IR utf (7)
|
||||
.SH DIAGNOSTICS
|
||||
.I Bio
|
||||
routines that return integers yield
|
||||
.B Beof
|
||||
if
|
||||
.I bp
|
||||
is not the descriptor of an open file.
|
||||
.I Bopen
|
||||
returns zero if the file cannot be opened in the given mode.
|
||||
.SH HISTORY
|
||||
The
|
||||
.IR bio (3)
|
||||
library originally appeared in Plan 9.
|
||||
This is a port of the Plan 9 bio library.
|
||||
.SH BUGS
|
||||
.I Brdline
|
||||
returns an error on strings longer than the buffer associated
|
||||
with the file
|
||||
and also if the end-of-file is encountered
|
||||
before a delimiter.
|
||||
.I Blinelen
|
||||
will tell how many characters are available
|
||||
in these cases.
|
||||
In the case of a true end-of-file,
|
||||
.I Blinelen
|
||||
will return zero.
|
||||
At the cost of allocating a buffer,
|
||||
.I Brdstr
|
||||
sidesteps these issues.
|
||||
.PP
|
||||
The data returned by
|
||||
.I Brdline
|
||||
may be overwritten by calls to any other
|
||||
.I bio
|
||||
routine on the same
|
||||
.IR bp.
|
||||
346
man/man3/fmtinstall.3
Normal file
346
man/man3/fmtinstall.3
Normal file
@@ -0,0 +1,346 @@
|
||||
.TH FMTINSTALL 3
|
||||
.de EX
|
||||
.nf
|
||||
.ft B
|
||||
..
|
||||
.de EE
|
||||
.fi
|
||||
.ft R
|
||||
..
|
||||
.SH NAME
|
||||
fmtinstall, dofmt, fmtprint, fmtvprint, fmtstrcpy, fmtfdinit, fmtfdflush, fmtstrinit, fmtstrflush \- support for user-defined print formats and output routines
|
||||
.SH SYNOPSIS
|
||||
.B #include <fmt.h>
|
||||
.PP
|
||||
.ft L
|
||||
.nf
|
||||
.ta \w' 'u +\w' 'u +\w' 'u +\w' 'u +\w' 'u
|
||||
typedef struct Fmt Fmt;
|
||||
struct Fmt{
|
||||
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 character */
|
||||
int width;
|
||||
int prec;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
enum{
|
||||
FmtWidth = 1,
|
||||
FmtLeft = FmtWidth << 1,
|
||||
FmtPrec = FmtLeft << 1,
|
||||
FmtSharp = FmtPrec << 1,
|
||||
FmtSpace = FmtSharp << 1,
|
||||
FmtSign = FmtSpace << 1,
|
||||
FmtZero = FmtSign << 1,
|
||||
FmtUnsigned = FmtZero << 1,
|
||||
FmtShort = FmtUnsigned << 1,
|
||||
FmtLong = FmtShort << 1,
|
||||
FmtVLong = FmtLong << 1,
|
||||
FmtComma = FmtVLong << 1,
|
||||
FmtByte = FmtComma << 1,
|
||||
FmtLDouble = FmtByte << 1,
|
||||
|
||||
FmtFlag = FmtLDouble << 1
|
||||
};
|
||||
.fi
|
||||
.PP
|
||||
.B
|
||||
.ta \w'\fLchar* 'u
|
||||
|
||||
.PP
|
||||
.B
|
||||
int fmtfdinit(Fmt *f, int fd, char *buf, int nbuf);
|
||||
.PP
|
||||
.B
|
||||
int fmtfdflush(Fmt *f);
|
||||
.PP
|
||||
.B
|
||||
int fmtstrinit(Fmt *f);
|
||||
.PP
|
||||
.B
|
||||
char* fmtstrflush(Fmt *f);
|
||||
.PP
|
||||
.B
|
||||
int fmtinstall(int c, int (*fn)(Fmt*));
|
||||
.PP
|
||||
.B
|
||||
int dofmt(Fmt *f, char *fmt);
|
||||
.PP
|
||||
.B
|
||||
int fmtprint(Fmt *f, char *fmt, ...);
|
||||
.PP
|
||||
.B
|
||||
int fmtvprint(Fmt *f, char *fmt, va_list v);
|
||||
.PP
|
||||
.B
|
||||
int fmtrune(Fmt *f, int r);
|
||||
.PP
|
||||
.B
|
||||
int fmtstrcpy(Fmt *f, char *s);
|
||||
.SH DESCRIPTION
|
||||
The interface described here allows the construction of custom
|
||||
.IR print (3)
|
||||
verbs and output routines.
|
||||
In essence, they provide access to the workings of the formatted print code.
|
||||
.PP
|
||||
The
|
||||
.IR print (3)
|
||||
suite maintains its state with a data structure called
|
||||
.BR Fmt .
|
||||
A typical call to
|
||||
.IR print (3)
|
||||
or its relatives initializes a
|
||||
.B Fmt
|
||||
structure, passes it to subsidiary routines to process the output,
|
||||
and finishes by emitting any saved state recorded in the
|
||||
.BR Fmt .
|
||||
The details of the
|
||||
.B Fmt
|
||||
are unimportant to outside users, except insofar as the general
|
||||
design influences the interface.
|
||||
The
|
||||
.B Fmt
|
||||
records
|
||||
the verb being processed, its precision and width,
|
||||
and buffering parameters.
|
||||
Most important, it also records a
|
||||
.I flush
|
||||
routine that the library will call if a buffer overflows.
|
||||
When printing to a file descriptor, the flush routine will
|
||||
emit saved characters and reset the buffer; when printing
|
||||
to an allocated string, it will resize the string to receive more output.
|
||||
The flush routine is nil when printing to fixed-size buffers.
|
||||
User code need never provide a flush routine; this is done internally
|
||||
by the library.
|
||||
.SS Custom output routines
|
||||
To write a custom output routine, such as an error handler that
|
||||
formats and prints custom error messages, the output sequence can be run
|
||||
from outside the library using the routines described here.
|
||||
There are two main cases: output to an open file descriptor
|
||||
and output to a string.
|
||||
.PP
|
||||
To write to a file descriptor, call
|
||||
.I fmtfdinit
|
||||
to initialize the local
|
||||
.B Fmt
|
||||
structure
|
||||
.IR f ,
|
||||
giving the file descriptor
|
||||
.IR fd ,
|
||||
the buffer
|
||||
.IR buf ,
|
||||
and its size
|
||||
.IR nbuf .
|
||||
Then call
|
||||
.IR fmtprint
|
||||
or
|
||||
.IR fmtvprint
|
||||
to generate the output.
|
||||
These behave just like
|
||||
.B fprint
|
||||
(see
|
||||
.IR print (3))
|
||||
or
|
||||
.B vfprint
|
||||
except that the characters are buffered until
|
||||
.I fmtfdflush
|
||||
is called.
|
||||
A typical example of this sequence appears in the Examples section.
|
||||
.PP
|
||||
The same basic sequence applies when outputting to an allocated string:
|
||||
call
|
||||
.I fmtstrinit
|
||||
to initialize the
|
||||
.BR Fmt ,
|
||||
then call
|
||||
.I fmtprint
|
||||
and
|
||||
.I fmtvprint
|
||||
to generate the output.
|
||||
Finally,
|
||||
.I fmtstrflush
|
||||
will return the allocated string, which should be freed after use.
|
||||
Regardless of the output style or type,
|
||||
.I fmtprint
|
||||
or
|
||||
.I fmtvprint
|
||||
generates the characters.
|
||||
.SS Custom format verbs
|
||||
.I Fmtinstall
|
||||
is used to install custom verbs and flags labeled by character
|
||||
.IR c ,
|
||||
which may be any non-zero Unicode character.
|
||||
.I Fn
|
||||
should be declared as
|
||||
.IP
|
||||
.EX
|
||||
int fn(Fmt*)
|
||||
.EE
|
||||
.PP
|
||||
.IB Fp ->r
|
||||
is the flag or verb character to cause
|
||||
.I fn
|
||||
to be called.
|
||||
In
|
||||
.IR fn ,
|
||||
.IB fp ->width ,
|
||||
.IB fp ->prec
|
||||
are the width and precision, and
|
||||
.IB fp ->flags
|
||||
the decoded flags for the verb (see
|
||||
.IR print (3)
|
||||
for a description of these items).
|
||||
The standard flag values are:
|
||||
.B FmtSign
|
||||
.RB ( + ),
|
||||
.B FmtLeft
|
||||
.RB ( - ),
|
||||
.B FmtSpace
|
||||
.RB ( '\ ' ),
|
||||
.B FmtSharp
|
||||
.RB ( # ),
|
||||
.B FmtComma
|
||||
.RB ( , ),
|
||||
.B FmtLong
|
||||
.RB ( l ),
|
||||
.B FmtShort
|
||||
.RB ( h ),
|
||||
.B FmtByte
|
||||
.RB ( hh ),
|
||||
.B FmtUnsigned
|
||||
.RB ( u ),
|
||||
.B FmtLDouble
|
||||
.RB ( L ),
|
||||
and
|
||||
.B FmtVLong
|
||||
.RB ( ll ).
|
||||
The flag bits
|
||||
.B FmtWidth
|
||||
and
|
||||
.B FmtPrec
|
||||
identify whether a width and precision were specified.
|
||||
.PP
|
||||
.I Fn
|
||||
is passed a pointer to the
|
||||
.B Fmt
|
||||
structure recording the state of the output.
|
||||
If
|
||||
.IB fp ->r
|
||||
is a verb (rather than a flag),
|
||||
.I fn
|
||||
should use
|
||||
.B Fmt->args
|
||||
to fetch its argument from the list,
|
||||
then format it, and return zero.
|
||||
If
|
||||
.IB fp ->r
|
||||
is a flag,
|
||||
.I fn
|
||||
should return a negative value:
|
||||
the negation of one of the above flag values, or some otherwise unused power of two.
|
||||
All interpretation of
|
||||
.IB fp ->width\f1,
|
||||
.IB fp ->prec\f1,
|
||||
and
|
||||
.IB fp-> flags
|
||||
is left up to the conversion routine.
|
||||
.I Fmtinstall
|
||||
returns 0 if the installation succeeds, \-1 if it fails.
|
||||
.PP
|
||||
.IR Fmtprint
|
||||
and
|
||||
.IR fmtvprint
|
||||
may be called to
|
||||
help prepare output in custom conversion routines.
|
||||
However, these functions clear the width, precision, and flags.
|
||||
The function
|
||||
.I dofmt
|
||||
is the underlying formatter; it
|
||||
uses the existing contents of
|
||||
.B Fmt
|
||||
and should be called only by sophisticated conversion routines.
|
||||
All these routines return the number of characters
|
||||
produced.
|
||||
.PP
|
||||
Some internal functions may be useful to format primitive types.
|
||||
They honor the width, precision and flags as described in
|
||||
.IR print (3).
|
||||
.I Fmtrune
|
||||
formats a single character
|
||||
.BR r .
|
||||
.I Fmtstrcpy
|
||||
formats a string
|
||||
.BR s .
|
||||
All these routines return zero for successful execution.
|
||||
.SH EXAMPLES
|
||||
This function prints an error message with a variable
|
||||
number of arguments and then quits.
|
||||
Compared to the corresponding example in
|
||||
.IR print (3),
|
||||
this version uses a smaller buffer, will never truncate
|
||||
the output message, but might generate multiple
|
||||
.B write
|
||||
system calls to produce its output.
|
||||
.IP
|
||||
.EX
|
||||
.ta 6n +6n +6n +6n +6n +6n +6n +6n +6n
|
||||
|
||||
void fatal(char *fmt, ...)
|
||||
{
|
||||
Fmt f;
|
||||
char buf[64];
|
||||
va_list arg;
|
||||
|
||||
fmtfdinit(&f, 1, buf, sizeof buf);
|
||||
fmtprint(&f, "fatal: ");
|
||||
va_start(arg, fmt);
|
||||
fmtvprint(&f, fmt, arg);
|
||||
va_end(arg);
|
||||
fmtprint(&f, "\en");
|
||||
fmtfdflush(&f);
|
||||
exits("fatal error");
|
||||
}
|
||||
.EE
|
||||
.PP
|
||||
This example adds a verb to print complex numbers.
|
||||
.IP
|
||||
.EX
|
||||
typedef
|
||||
struct {
|
||||
double r, i;
|
||||
} Complex;
|
||||
|
||||
int
|
||||
Xfmt(Fmt *f)
|
||||
{
|
||||
Complex c;
|
||||
|
||||
c = va_arg(f->args, Complex);
|
||||
return fmtprint(f, "(%g,%g)", c.r, c.i);
|
||||
}
|
||||
|
||||
main(...)
|
||||
{
|
||||
Complex x;
|
||||
|
||||
x.r = 1.5;
|
||||
x.i = -2.3;
|
||||
|
||||
fmtinstall('X', Xfmt);
|
||||
print("x = %X\en", x);
|
||||
}
|
||||
.EE
|
||||
.SH SEE ALSO
|
||||
.IR print (3)
|
||||
.SH HISTORY
|
||||
This formatted print library originally
|
||||
appeared as part of the Plan 9 C library.
|
||||
.SH BUGS
|
||||
The Plan 9 version supports Unicode strings and produces UTF output.
|
||||
This version assumes that characters are always represented by 1-byte values.
|
||||
179
man/man3/ioproc.3
Normal file
179
man/man3/ioproc.3
Normal file
@@ -0,0 +1,179 @@
|
||||
.TH IOPROC 2
|
||||
.SH NAME
|
||||
closeioproc,
|
||||
iocall,
|
||||
ioclose,
|
||||
iointerrupt,
|
||||
iodial,
|
||||
ioopen,
|
||||
ioproc,
|
||||
ioread,
|
||||
ioreadn,
|
||||
iowrite \- slave I/O processes for threaded programs
|
||||
.SH SYNOPSIS
|
||||
.PP
|
||||
.de XX
|
||||
.ift .sp 0.5
|
||||
.ifn .sp
|
||||
..
|
||||
.EX
|
||||
.ta \w'Ioproc* 'u
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
.sp
|
||||
typedef struct Ioproc Ioproc;
|
||||
.sp
|
||||
Ioproc* ioproc(void);
|
||||
.XX
|
||||
int ioopen(Ioproc *io, char *file, int omode);
|
||||
int ioclose(Ioproc *io, int fd);
|
||||
long ioread(Ioproc *io, int fd, void *a, long n);
|
||||
long ioreadn(Ioproc *io, int fd, void *a, long n);
|
||||
long iowrite(Ioproc *io, int fd, void *a, long n);
|
||||
int iodial(Ioproc *io, char *addr, char *local, char *dir, char *cdfp);
|
||||
.XX
|
||||
void iointerrupt(Ioproc *io);
|
||||
void closeioproc(Ioproc *io);
|
||||
.XX
|
||||
long iocall(Ioproc *io, long (*op)(va_list *arg), ...);
|
||||
.EE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
These routines provide access to I/O in slave procs.
|
||||
Since the I/O itself is done in a slave proc, other threads
|
||||
in the calling proc can run while the calling thread
|
||||
waits for the I/O to complete.
|
||||
.PP
|
||||
.I Ioproc
|
||||
forks a new slave proc and returns a pointer to the
|
||||
.B Ioproc
|
||||
associated with it.
|
||||
.I Ioproc
|
||||
uses
|
||||
.I mallocz
|
||||
and
|
||||
.IR proccreate ;
|
||||
if either fails, it calls
|
||||
.I sysfatal
|
||||
rather than return an error.
|
||||
.PP
|
||||
.IR Ioopen ,
|
||||
.IR ioclose ,
|
||||
.IR ioread ,
|
||||
.IR ioreadn ,
|
||||
.IR iowrite ,
|
||||
and
|
||||
.IR iodial
|
||||
are execute the
|
||||
similarly named library or system calls
|
||||
(see
|
||||
.IR open (2),
|
||||
.IR read (2),
|
||||
and
|
||||
.IR dial (2))
|
||||
in the slave process associated with
|
||||
.IR io .
|
||||
It is an error to execute more than one call
|
||||
at a time in an I/O proc.
|
||||
.PP
|
||||
.I Iointerrupt
|
||||
interrupts the call currently executing in the I/O proc.
|
||||
If no call is executing,
|
||||
.IR iointerrupt
|
||||
is a no-op.
|
||||
.PP
|
||||
.I Closeioproc
|
||||
terminates the I/O proc and frees the associated
|
||||
.B Ioproc .
|
||||
.PP
|
||||
.I Iocall
|
||||
is a primitive that may be used to implement
|
||||
more slave I/O routines.
|
||||
.I Iocall
|
||||
arranges for
|
||||
.I op
|
||||
to be called in
|
||||
.IR io 's
|
||||
proc, with
|
||||
.I arg
|
||||
set to the variable parameter list,
|
||||
returning the value that
|
||||
.I op
|
||||
returns.
|
||||
.SH EXAMPLE
|
||||
Relay messages between two file descriptors,
|
||||
counting the total number of bytes seen:
|
||||
.IP
|
||||
.EX
|
||||
.ta +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u
|
||||
int tot;
|
||||
|
||||
void
|
||||
relaythread(void *v)
|
||||
{
|
||||
int *fd, n;
|
||||
char buf[1024];
|
||||
Ioproc *io;
|
||||
|
||||
fd = v;
|
||||
io = ioproc();
|
||||
while((n = ioread(io, fd[0], buf, sizeof buf)) > 0){
|
||||
if(iowrite(io, fd[1], buf, n) != n)
|
||||
sysfatal("iowrite: %r");
|
||||
tot += n;
|
||||
}
|
||||
closeioproc(io);
|
||||
}
|
||||
|
||||
void
|
||||
relay(int fd0, int fd1)
|
||||
{
|
||||
int fd[4];
|
||||
|
||||
fd[0] = fd[3] = fd0;
|
||||
fd[1] = fd[2] = fd1;
|
||||
threadcreate(relaythread, fd, 8192);
|
||||
threadcreate(relaythread, fd+2, 8192);
|
||||
}
|
||||
.EE
|
||||
.LP
|
||||
If the two
|
||||
.I relaythread
|
||||
instances were running in different procs, the
|
||||
common access to
|
||||
.I tot
|
||||
would be unsafe.
|
||||
.EE
|
||||
.PP
|
||||
Implement
|
||||
.IR ioread :
|
||||
.IP
|
||||
.EX
|
||||
static long
|
||||
_ioread(va_list *arg)
|
||||
{
|
||||
int fd;
|
||||
void *a;
|
||||
long n;
|
||||
|
||||
fd = va_arg(*arg, int);
|
||||
a = va_arg(*arg, void*);
|
||||
n = va_arg(*arg, long);
|
||||
return read(fd, a, n);
|
||||
}
|
||||
|
||||
long
|
||||
ioread(Ioproc *io, int fd, void *a, long n)
|
||||
{
|
||||
return iocall(io, _ioread, fd, a, n);
|
||||
}
|
||||
.EE
|
||||
.SH SOURCE
|
||||
.B /sys/src/libthread/io*.c
|
||||
.SH SEE ALSO
|
||||
.IR dial (2),
|
||||
.IR open (2),
|
||||
.IR read (2),
|
||||
.IR thread (2)
|
||||
|
||||
47
man/man3/isalpharune.3
Normal file
47
man/man3/isalpharune.3
Normal file
@@ -0,0 +1,47 @@
|
||||
.TH ISALPHARUNE 3
|
||||
.SH NAME
|
||||
isalpharune, islowerrune, isspacerune, istitlerune, isupperrune, tolowerrune, totitlerune, toupperrune \- Unicode character classes and cases
|
||||
.SH SYNOPSIS
|
||||
.B #include <utf.h>
|
||||
.PP
|
||||
.B
|
||||
int isalpharune(Rune c)
|
||||
.PP
|
||||
.B
|
||||
int islowerrune(Rune c)
|
||||
.PP
|
||||
.B
|
||||
int isspacerune(Rune c)
|
||||
.PP
|
||||
.B
|
||||
int istitlerune(Rune c)
|
||||
.PP
|
||||
.B
|
||||
int isupperrune(Rune c)
|
||||
.PP
|
||||
.B
|
||||
Rune tolowerrune(Rune c)
|
||||
.PP
|
||||
.B
|
||||
Rune totitlerune(Rune c)
|
||||
.PP
|
||||
.B
|
||||
Rune toupperrune(Rune c)
|
||||
.SH DESCRIPTION
|
||||
These routines examine and operate on Unicode characters,
|
||||
in particular a subset of their properties as defined in the Unicode standard.
|
||||
Unicode defines some characters as alphabetic and specifies three cases:
|
||||
upper, lower, and title.
|
||||
Analogously to
|
||||
.IR ctype (3)
|
||||
for
|
||||
.SM ASCII\c
|
||||
,
|
||||
these routines
|
||||
test types and modify cases for Unicode characters.
|
||||
The names are self-explanatory.
|
||||
.PP
|
||||
The case-conversion routines return the character unchanged if it has no case.
|
||||
.SH "SEE ALSO
|
||||
.IR ctype (3) ,
|
||||
.IR "The Unicode Standard" .
|
||||
469
man/man3/print.3
Normal file
469
man/man3/print.3
Normal file
@@ -0,0 +1,469 @@
|
||||
.TH PRINT 3
|
||||
.de EX
|
||||
.nf
|
||||
.ft B
|
||||
..
|
||||
.de EE
|
||||
.fi
|
||||
.ft R
|
||||
..
|
||||
.SH NAME
|
||||
print, fprint, sprint, snprint, seprint, smprint, vfprint, vsnprint, vseprint, vsmprint \- print formatted output
|
||||
.SH SYNOPSIS
|
||||
.B #include <utf.h>
|
||||
.PP
|
||||
.B #include <fmt.h>
|
||||
.PP
|
||||
.ta \w'\fLchar* 'u
|
||||
.B
|
||||
int print(char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int fprint(int fd, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int sprint(char *s, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int snprint(char *s, int len, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
char* seprint(char *s, char *e, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
char* smprint(char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int runesprint(Rune *s, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int runesnprint(Rune *s, int len, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
Rune* runeseprint(Rune *s, Rune *e, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
Rune* runesmprint(char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int vfprint(int fd, char *format, va_list v)
|
||||
.PP
|
||||
.B
|
||||
int vsnprint(char *s, int len, char *format, va_list v)
|
||||
.PP
|
||||
.B
|
||||
char* vseprint(char *s, char *e, char *format, va_list v)
|
||||
.PP
|
||||
.B
|
||||
char* vsmprint(char *format, va_list v)
|
||||
.PP
|
||||
.B
|
||||
int runevsnprint(Rune *s, int len, char *format, va_list v)
|
||||
.PP
|
||||
.B
|
||||
Rune* runevseprint(Rune *s, Rune *e, char *format, va_list v)
|
||||
.PP
|
||||
.B
|
||||
Rune* runevsmprint(Rune *format, va_list v)
|
||||
.PP
|
||||
.B
|
||||
.SH DESCRIPTION
|
||||
.I Print
|
||||
writes text to the standard output.
|
||||
.I Fprint
|
||||
writes to the named output
|
||||
file descriptor.
|
||||
.I Sprint
|
||||
places text
|
||||
followed by the NUL character
|
||||
.RB ( \e0 )
|
||||
in consecutive bytes starting at
|
||||
.IR s ;
|
||||
it is the user's responsibility to ensure that
|
||||
enough storage is available.
|
||||
Each function returns the number of bytes
|
||||
transmitted (not including the NUL
|
||||
in the case of
|
||||
.IR sprint ),
|
||||
or
|
||||
a negative value if an output error was encountered.
|
||||
.PP
|
||||
.I Snprint
|
||||
is like
|
||||
.IR sprint ,
|
||||
but will not place more than
|
||||
.I len
|
||||
bytes in
|
||||
.IR s .
|
||||
Its result is always NUL-terminated and holds the maximal
|
||||
number of characters that can fit.
|
||||
.I Seprint
|
||||
is like
|
||||
.IR snprint ,
|
||||
except that the end is indicated by a pointer
|
||||
.I e
|
||||
rather than a count and the return value points to the terminating NUL of the
|
||||
resulting string.
|
||||
.I Smprint
|
||||
is like
|
||||
.IR sprint ,
|
||||
except that it prints into and returns a string of the required length, which is
|
||||
allocated by
|
||||
.IR malloc (3).
|
||||
.PP
|
||||
The routines
|
||||
.IR runesprint ,
|
||||
.IR runesnprint ,
|
||||
.IR runeseprint ,
|
||||
and
|
||||
.I runesmprint
|
||||
are the same as
|
||||
.IR sprint ,
|
||||
.IR snprint ,
|
||||
.IR seprint
|
||||
and
|
||||
.I smprint
|
||||
except that their output is rune strings instead of byte strings.
|
||||
.PP
|
||||
Finally, the routines
|
||||
.IR vfprint ,
|
||||
.IR vsnprint ,
|
||||
.IR vseprint ,
|
||||
.IR vsmprint ,
|
||||
.IR runevsnprint ,
|
||||
.IR runevseprint ,
|
||||
and
|
||||
.I runevsmprint
|
||||
are like their
|
||||
.BR v-less
|
||||
relatives except they take as arguments a
|
||||
.B va_list
|
||||
parameter, so they can be called within a variadic function.
|
||||
The Example section shows a representative usage.
|
||||
.PP
|
||||
Each of these functions
|
||||
converts, formats, and prints its
|
||||
trailing arguments
|
||||
under control of a
|
||||
.IR format
|
||||
string.
|
||||
The
|
||||
format
|
||||
contains two types of objects:
|
||||
plain characters, which are simply copied to the
|
||||
output stream,
|
||||
and conversion specifications,
|
||||
each of which results in fetching of
|
||||
zero or more
|
||||
arguments.
|
||||
The results are undefined if there are arguments of the
|
||||
wrong type or too few
|
||||
arguments for the format.
|
||||
If the format is exhausted while
|
||||
arguments remain, the excess
|
||||
is ignored.
|
||||
.PP
|
||||
Each conversion specification has the following format:
|
||||
.IP
|
||||
.B "% [flags] verb
|
||||
.PP
|
||||
The verb is a single character and each flag is a single character or a
|
||||
(decimal) numeric string.
|
||||
Up to two numeric strings may be used;
|
||||
the first is called
|
||||
.IR width ,
|
||||
the second
|
||||
.IR precision .
|
||||
A period can be used to separate them, and if the period is
|
||||
present then
|
||||
.I width
|
||||
and
|
||||
.I precision
|
||||
are taken to be zero if missing, otherwise they are `omitted'.
|
||||
Either or both of the numbers may be replaced with the character
|
||||
.BR * ,
|
||||
meaning that the actual number will be obtained from the argument list
|
||||
as an integer.
|
||||
The flags and numbers are arguments to
|
||||
the
|
||||
.I verb
|
||||
described below.
|
||||
.PP
|
||||
The numeric verbs
|
||||
.BR d ,
|
||||
.BR i ,
|
||||
.BR u ,
|
||||
.BR o ,
|
||||
.BR b ,
|
||||
.BR x ,
|
||||
and
|
||||
.B X
|
||||
format their arguments in decimal, decimal,
|
||||
unsigned decimal, octal, binary, hexadecimal, and upper case hexadecimal.
|
||||
Each interprets the flags
|
||||
.BR 0 ,
|
||||
.BR h ,
|
||||
.BR hh ,
|
||||
.BR l ,
|
||||
.BR + ,
|
||||
.BR - ,
|
||||
.BR , ,
|
||||
and
|
||||
.B #
|
||||
to mean pad with zeros,
|
||||
short, byte, long, always print a sign, left justified, commas every three digits,
|
||||
and alternate format.
|
||||
Also, a space character in the flag
|
||||
position is like
|
||||
.BR + ,
|
||||
but prints a space instead of a plus sign for non-negative values.
|
||||
If neither
|
||||
short nor long is specified,
|
||||
then the argument is an
|
||||
.BR int .
|
||||
If an unsigned verb is specified,
|
||||
then the argument is interpreted as a
|
||||
positive number and no sign is output;
|
||||
space and
|
||||
.B +
|
||||
flags are ignored for unsigned verbs.
|
||||
If two
|
||||
.B l
|
||||
flags are given,
|
||||
then the argument is interpreted as a
|
||||
.B vlong
|
||||
(usually an 8-byte, sometimes a 4-byte integer).
|
||||
If
|
||||
.I precision
|
||||
is not omitted, the number is padded on the left with zeros
|
||||
until at least
|
||||
.I precision
|
||||
digits appear.
|
||||
If
|
||||
.I precision
|
||||
is explicitly 0, and the number is 0,
|
||||
no digits are generated, and alternate formatting
|
||||
does not apply.
|
||||
Then, if alternate format is specified,
|
||||
for
|
||||
.B o
|
||||
conversion, the number is preceded by a
|
||||
.B 0
|
||||
if it doesn't already begin with one.
|
||||
For non-zero numbers and
|
||||
.B x
|
||||
conversion, the number is preceded by
|
||||
.BR 0x ;
|
||||
for
|
||||
.B X
|
||||
conversion, the number is preceded by
|
||||
.BR 0X .
|
||||
Finally, if
|
||||
.I width
|
||||
is not omitted, the number is padded on the left (or right, if
|
||||
left justification is specified) with enough blanks to
|
||||
make the field at least
|
||||
.I width
|
||||
characters long.
|
||||
.PP
|
||||
The floating point verbs
|
||||
.BR f ,
|
||||
.BR e ,
|
||||
.BR E ,
|
||||
.BR g ,
|
||||
and
|
||||
.B G
|
||||
take a
|
||||
.B double
|
||||
argument.
|
||||
Each interprets the flags
|
||||
.BR 0 ,
|
||||
.BR L
|
||||
.BR + ,
|
||||
.BR - ,
|
||||
and
|
||||
.B #
|
||||
to mean pad with zeros,
|
||||
long double argument,
|
||||
always print a sign,
|
||||
left justified,
|
||||
and
|
||||
alternate format.
|
||||
.I Width
|
||||
is the minimum field width and,
|
||||
if the converted value takes up less than
|
||||
.I width
|
||||
characters, it is padded on the left (or right, if `left justified')
|
||||
with spaces.
|
||||
.I Precision
|
||||
is the number of digits that are converted after the decimal place for
|
||||
.BR e ,
|
||||
.BR E ,
|
||||
and
|
||||
.B f
|
||||
conversions,
|
||||
and
|
||||
.I precision
|
||||
is the maximum number of significant digits for
|
||||
.B g
|
||||
and
|
||||
.B G
|
||||
conversions.
|
||||
The
|
||||
.B f
|
||||
verb produces output of the form
|
||||
.RB [ - ] digits [ .digits\fR].
|
||||
.B E
|
||||
conversion appends an exponent
|
||||
.BR E [ - ] digits ,
|
||||
and
|
||||
.B e
|
||||
conversion appends an exponent
|
||||
.BR e [ - ] digits .
|
||||
The
|
||||
.B g
|
||||
verb will output the argument in either
|
||||
.B e
|
||||
or
|
||||
.B f
|
||||
with the goal of producing the smallest output.
|
||||
Also, trailing zeros are omitted from the fraction part of
|
||||
the output, and a trailing decimal point appears only if it is followed
|
||||
by a digit.
|
||||
The
|
||||
.B G
|
||||
verb is similar, but uses
|
||||
.B E
|
||||
format instead of
|
||||
.BR e .
|
||||
When alternate format is specified, the result will always contain a decimal point,
|
||||
and for
|
||||
.B g
|
||||
and
|
||||
.B G
|
||||
conversions, trailing zeros are not removed.
|
||||
.PP
|
||||
The
|
||||
.B s
|
||||
verb copies a string
|
||||
(pointer to
|
||||
.BR char )
|
||||
to the output.
|
||||
The number of characters copied
|
||||
.RI ( n )
|
||||
is the minimum
|
||||
of the size of the string and
|
||||
.IR precision .
|
||||
These
|
||||
.I n
|
||||
characters are justified within a field of
|
||||
.I width
|
||||
characters as described above.
|
||||
If a
|
||||
.I precision
|
||||
is given, it is safe for the string not to be nul-terminated
|
||||
as long as it is at least
|
||||
.I precision
|
||||
characters (not bytes!) long.
|
||||
The
|
||||
.B S
|
||||
verb is similar, but it interprets its pointer as an array
|
||||
of runes (see
|
||||
.IR utf (7));
|
||||
the runes are converted to
|
||||
.SM UTF
|
||||
before output.
|
||||
.PP
|
||||
The
|
||||
.B c
|
||||
verb copies a single
|
||||
.B char
|
||||
(promoted to
|
||||
.BR int )
|
||||
justified within a field of
|
||||
.I width
|
||||
characters as described above.
|
||||
The
|
||||
.B C
|
||||
verb is similar, but works on runes.
|
||||
.PP
|
||||
The
|
||||
.B p
|
||||
verb formats a pointer value.
|
||||
At the moment, it is a synonym for
|
||||
.BR x ,
|
||||
but that will change if pointers and integers are different sizes.
|
||||
.PP
|
||||
The
|
||||
.B r
|
||||
verb takes no arguments; it copies the error string returned by a call to
|
||||
.IR strerror (3)
|
||||
with an argument of
|
||||
.IR errno.
|
||||
.PP
|
||||
Custom verbs may be installed using
|
||||
.IR fmtinstall (3).
|
||||
.SH EXAMPLE
|
||||
This function prints an error message with a variable
|
||||
number of arguments and then quits.
|
||||
.IP
|
||||
.EX
|
||||
.ta 6n +6n +6n
|
||||
void fatal(char *msg, ...)
|
||||
{
|
||||
char buf[1024], *out;
|
||||
va_list arg;
|
||||
|
||||
out = vseprint(buf, buf+sizeof buf, "Fatal error: ");
|
||||
va_start(arg, msg);
|
||||
out = vseprint(out, buf+sizeof buf, msg, arg);
|
||||
va_end(arg);
|
||||
write(2, buf, out-buf);
|
||||
exit(1);
|
||||
}
|
||||
.EE
|
||||
.SH SEE ALSO
|
||||
.IR fmtinstall (3),
|
||||
.IR fprintf (3),
|
||||
.IR utf (7)
|
||||
.SH DIAGNOSTICS
|
||||
Routines that write to a file descriptor or call
|
||||
.IR malloc
|
||||
set
|
||||
.IR errstr .
|
||||
.SH BUGS
|
||||
The formatting is close to that specified for ANSI
|
||||
.IR fprintf (3);
|
||||
the main difference is that
|
||||
.B b
|
||||
and
|
||||
.B r
|
||||
are not in ANSI and some
|
||||
.B C9X
|
||||
verbs are missing.
|
||||
Also, and distinctly not a bug,
|
||||
.I print
|
||||
and friends generate
|
||||
.SM UTF
|
||||
rather than
|
||||
.SM ASCII.
|
||||
.PP
|
||||
There is no
|
||||
.BR runeprint ,
|
||||
.BR runefprint ,
|
||||
etc. because runes are byte-order dependent and should not be written directly to a file; use the
|
||||
UTF output of
|
||||
.I print
|
||||
or
|
||||
.I fprint
|
||||
instead.
|
||||
Also,
|
||||
.I sprint
|
||||
is deprecated for safety reasons; use
|
||||
.IR snprint ,
|
||||
.IR seprint ,
|
||||
or
|
||||
.I smprint
|
||||
instead.
|
||||
Safety also precludes the existence of
|
||||
.IR runesprint .
|
||||
227
man/man3/regexp9.3
Normal file
227
man/man3/regexp9.3
Normal file
@@ -0,0 +1,227 @@
|
||||
.TH REGEXP9 3
|
||||
.de EX
|
||||
.nf
|
||||
.ft B
|
||||
..
|
||||
.de EE
|
||||
.fi
|
||||
.ft R
|
||||
..
|
||||
.de LR
|
||||
.if t .BR \\$1 \\$2
|
||||
.if n .RB ` \\$1 '\\$2
|
||||
..
|
||||
.de L
|
||||
.nh
|
||||
.if t .B \\$1
|
||||
.if n .RB ` \\$1 '
|
||||
..
|
||||
.SH NAME
|
||||
regcomp, regcomplit, regcompnl, regexec, regsub, regerror \- Plan 9 regular expression library
|
||||
.SH SYNOPSIS
|
||||
.B #include <regexp9.h>
|
||||
.PP
|
||||
.ta \w'\fLRegprog 'u
|
||||
.B
|
||||
Reprog *regcomp(char *exp)
|
||||
.PP
|
||||
.B
|
||||
Reprog *regcomplit(char *exp)
|
||||
.PP
|
||||
.B
|
||||
Reprog *regcompnl(char *exp)
|
||||
.PP
|
||||
.nf
|
||||
.B
|
||||
int regexec(Reprog *prog, char *string, Resub *match, int msize)
|
||||
.PP
|
||||
.nf
|
||||
.B
|
||||
void regsub(char *source, char *dest, int dlen, Resub *match, int msize)
|
||||
.PP
|
||||
.nf
|
||||
.B
|
||||
int rregexec(Reprog *prog, Rune *string, Resub *match, int msize)
|
||||
.PP
|
||||
.nf
|
||||
.B
|
||||
void rregsub(Rune *source, Rune *dest, int dlen, Resub *match, int msize)
|
||||
.PP
|
||||
.B
|
||||
void regerror(char *msg)
|
||||
.SH DESCRIPTION
|
||||
.I Regcomp
|
||||
compiles a
|
||||
regular expression and returns
|
||||
a pointer to the generated description.
|
||||
The space is allocated by
|
||||
.IR malloc (3)
|
||||
and may be released by
|
||||
.IR free .
|
||||
Regular expressions are exactly as in
|
||||
.IR regexp9 (7).
|
||||
.PP
|
||||
.I Regcomplit
|
||||
is like
|
||||
.I regcomp
|
||||
except that all characters are treated literally.
|
||||
.I Regcompnl
|
||||
is like
|
||||
.I regcomp
|
||||
except that the
|
||||
.B .
|
||||
metacharacter matches all characters, including newlines.
|
||||
.PP
|
||||
.I Regexec
|
||||
matches a null-terminated
|
||||
.I string
|
||||
against the compiled regular expression in
|
||||
.IR prog .
|
||||
If it matches,
|
||||
.I regexec
|
||||
returns
|
||||
.B 1
|
||||
and fills in the array
|
||||
.I match
|
||||
with character pointers to the substrings of
|
||||
.I string
|
||||
that correspond to the
|
||||
parenthesized subexpressions of
|
||||
.IR exp :
|
||||
.BI match[ i ].sp
|
||||
points to the beginning and
|
||||
.BI match[ i ].ep
|
||||
points just beyond
|
||||
the end of the
|
||||
.IR i th
|
||||
substring.
|
||||
(Subexpression
|
||||
.I i
|
||||
begins at the
|
||||
.IR i th
|
||||
left parenthesis, counting from 1.)
|
||||
Pointers in
|
||||
.B match[0]
|
||||
pick out the substring that corresponds to
|
||||
the whole regular expression.
|
||||
Unused elements of
|
||||
.I match
|
||||
are filled with zeros.
|
||||
Matches involving
|
||||
.LR * ,
|
||||
.LR + ,
|
||||
and
|
||||
.L ?
|
||||
are extended as far as possible.
|
||||
The number of array elements in
|
||||
.I match
|
||||
is given by
|
||||
.IR msize .
|
||||
The structure of elements of
|
||||
.I match
|
||||
is:
|
||||
.IP
|
||||
.EX
|
||||
typedef struct {
|
||||
union {
|
||||
char *sp;
|
||||
Rune *rsp;
|
||||
} s;
|
||||
union {
|
||||
char *ep;
|
||||
Rune *rep;
|
||||
} e;
|
||||
} Resub;
|
||||
.EE
|
||||
.LP
|
||||
If
|
||||
.B match[0].s.sp
|
||||
is nonzero on entry,
|
||||
.I regexec
|
||||
starts matching at that point within
|
||||
.IR string .
|
||||
If
|
||||
.B match[0].e.ep
|
||||
is nonzero on entry,
|
||||
the last character matched is the one
|
||||
preceding that point.
|
||||
.PP
|
||||
.I Regsub
|
||||
places in
|
||||
.I dest
|
||||
a substitution instance of
|
||||
.I source
|
||||
in the context of the last
|
||||
.I regexec
|
||||
performed using
|
||||
.IR match .
|
||||
Each instance of
|
||||
.BI \e n\f1,
|
||||
where
|
||||
.I n
|
||||
is a digit, is replaced by the
|
||||
string delimited by
|
||||
.BI match[ n ].s.sp
|
||||
and
|
||||
.BI match[ n ].e.ep\f1.
|
||||
Each instance of
|
||||
.L &
|
||||
is replaced by the string delimited by
|
||||
.B match[0].s.sp
|
||||
and
|
||||
.BR match[0].e.ep .
|
||||
The substitution will always be null terminated and
|
||||
trimmed to fit into dlen bytes.
|
||||
.PP
|
||||
.IR Regerror ,
|
||||
called whenever an error is detected in
|
||||
.IR regcomp ,
|
||||
writes the string
|
||||
.I msg
|
||||
on the standard error file and exits.
|
||||
.I Regerror
|
||||
can be replaced to perform
|
||||
special error processing.
|
||||
If the user supplied
|
||||
.I regerror
|
||||
returns rather than exits,
|
||||
.I regcomp
|
||||
will return 0.
|
||||
.PP
|
||||
.I Rregexec
|
||||
and
|
||||
.I rregsub
|
||||
are variants of
|
||||
.I regexec
|
||||
and
|
||||
.I regsub
|
||||
that use strings of
|
||||
.B Runes
|
||||
instead of strings of
|
||||
.BR chars .
|
||||
With these routines, the
|
||||
.I rsp
|
||||
and
|
||||
.I rep
|
||||
fields of the
|
||||
.I match
|
||||
array elements should be used.
|
||||
.SH "SEE ALSO"
|
||||
.IR grep (1),
|
||||
.IR regexp9 (7)
|
||||
.SH DIAGNOSTICS
|
||||
.I Regcomp
|
||||
returns
|
||||
.B 0
|
||||
for an illegal expression
|
||||
or other failure.
|
||||
.I Regexec
|
||||
returns 0
|
||||
if
|
||||
.I string
|
||||
is not matched.
|
||||
.SH HISTORY
|
||||
This particular regular expression was first written by Rob Pike for Plan 9.
|
||||
It has also appeared as part of the Inferno operating system.
|
||||
.SH BUGS
|
||||
There is no way to specify or match a NUL character; NULs terminate patterns and strings.
|
||||
187
man/man3/rune.3
Normal file
187
man/man3/rune.3
Normal file
@@ -0,0 +1,187 @@
|
||||
.TH RUNE 3
|
||||
.SH NAME
|
||||
runetochar, chartorune, runelen, runenlen, fullrune, utfecpy, utflen, utfnlen, utfrune, utfrrune, utfutf \- rune/UTF conversion
|
||||
.SH SYNOPSIS
|
||||
.ta \w'\fLchar*xx'u
|
||||
.B #include <utf.h>
|
||||
.PP
|
||||
.B
|
||||
int runetochar(char *s, Rune *r)
|
||||
.PP
|
||||
.B
|
||||
int chartorune(Rune *r, char *s)
|
||||
.PP
|
||||
.B
|
||||
int runelen(long r)
|
||||
.PP
|
||||
.B
|
||||
int runenlen(Rune *r, int n)
|
||||
.PP
|
||||
.B
|
||||
int fullrune(char *s, int n)
|
||||
.PP
|
||||
.B
|
||||
char* utfecpy(char *s1, char *es1, char *s2)
|
||||
.PP
|
||||
.B
|
||||
int utflen(char *s)
|
||||
.PP
|
||||
.B
|
||||
int utfnlen(char *s, long n)
|
||||
.PP
|
||||
.B
|
||||
char* utfrune(char *s, long c)
|
||||
.PP
|
||||
.B
|
||||
char* utfrrune(char *s, long c)
|
||||
.PP
|
||||
.B
|
||||
char* utfutf(char *s1, char *s2)
|
||||
.SH DESCRIPTION
|
||||
These routines convert to and from a
|
||||
.SM UTF
|
||||
byte stream and runes.
|
||||
.PP
|
||||
.I Runetochar
|
||||
copies one rune at
|
||||
.I r
|
||||
to at most
|
||||
.B UTFmax
|
||||
bytes starting at
|
||||
.I s
|
||||
and returns the number of bytes copied.
|
||||
.BR UTFmax ,
|
||||
defined as
|
||||
.B 3
|
||||
in
|
||||
.BR <libc.h> ,
|
||||
is the maximum number of bytes required to represent a rune.
|
||||
.PP
|
||||
.I Chartorune
|
||||
copies at most
|
||||
.B UTFmax
|
||||
bytes starting at
|
||||
.I s
|
||||
to one rune at
|
||||
.I r
|
||||
and returns the number of bytes copied.
|
||||
If the input is not exactly in
|
||||
.SM UTF
|
||||
format,
|
||||
.I chartorune
|
||||
will convert to 0x80 and return 1.
|
||||
.PP
|
||||
.I Runelen
|
||||
returns the number of bytes
|
||||
required to convert
|
||||
.I r
|
||||
into
|
||||
.SM UTF.
|
||||
.PP
|
||||
.I Runenlen
|
||||
returns the number of bytes
|
||||
required to convert the
|
||||
.I n
|
||||
runes pointed to by
|
||||
.I r
|
||||
into
|
||||
.SM UTF.
|
||||
.PP
|
||||
.I Fullrune
|
||||
returns 1 if the string
|
||||
.I s
|
||||
of length
|
||||
.I n
|
||||
is long enough to be decoded by
|
||||
.I chartorune
|
||||
and 0 otherwise.
|
||||
This does not guarantee that the string
|
||||
contains a legal
|
||||
.SM UTF
|
||||
encoding.
|
||||
This routine is used by programs that
|
||||
obtain input a byte at
|
||||
a time and need to know when a full rune
|
||||
has arrived.
|
||||
.PP
|
||||
The following routines are analogous to the
|
||||
corresponding string routines with
|
||||
.B utf
|
||||
substituted for
|
||||
.B str
|
||||
and
|
||||
.B rune
|
||||
substituted for
|
||||
.BR chr .
|
||||
.PP
|
||||
.I Utfecpy
|
||||
copies UTF sequences until a null sequence has been copied, but writes no
|
||||
sequences beyond
|
||||
.IR es1 .
|
||||
If any sequences are copied,
|
||||
.I s1
|
||||
is terminated by a null sequence, and a pointer to that sequence is returned.
|
||||
Otherwise, the original
|
||||
.I s1
|
||||
is returned.
|
||||
.PP
|
||||
.I Utflen
|
||||
returns the number of runes that
|
||||
are represented by the
|
||||
.SM UTF
|
||||
string
|
||||
.IR s .
|
||||
.PP
|
||||
.I Utfnlen
|
||||
returns the number of complete runes that
|
||||
are represented by the first
|
||||
.I n
|
||||
bytes of
|
||||
.SM UTF
|
||||
string
|
||||
.IR s .
|
||||
If the last few bytes of the string contain an incompletely coded rune,
|
||||
.I utfnlen
|
||||
will not count them; in this way, it differs from
|
||||
.IR utflen ,
|
||||
which includes every byte of the string.
|
||||
.PP
|
||||
.I Utfrune
|
||||
.RI ( utfrrune )
|
||||
returns a pointer to the first (last)
|
||||
occurrence of rune
|
||||
.I c
|
||||
in the
|
||||
.SM UTF
|
||||
string
|
||||
.IR s ,
|
||||
or 0 if
|
||||
.I c
|
||||
does not occur in the string.
|
||||
The NUL byte terminating a string is considered to
|
||||
be part of the string
|
||||
.IR s .
|
||||
.PP
|
||||
.I Utfutf
|
||||
returns a pointer to the first occurrence of
|
||||
the
|
||||
.SM UTF
|
||||
string
|
||||
.I s2
|
||||
as a
|
||||
.SM UTF
|
||||
substring of
|
||||
.IR s1 ,
|
||||
or 0 if there is none.
|
||||
If
|
||||
.I s2
|
||||
is the null string,
|
||||
.I utfutf
|
||||
returns
|
||||
.IR s1 .
|
||||
.SH HISTORY
|
||||
These routines were written by Rob Pike and Ken Thompson
|
||||
and first appeared in Plan 9.
|
||||
.SH SEE ALSO
|
||||
.IR utf (7),
|
||||
.IR tcs (1)
|
||||
65
man/man3/runestrcat.3
Normal file
65
man/man3/runestrcat.3
Normal file
@@ -0,0 +1,65 @@
|
||||
.TH RUNESTRCAT 3
|
||||
.SH NAME
|
||||
runestrcat,
|
||||
runestrncat,
|
||||
runestrcmp,
|
||||
runestrncmp,
|
||||
runestrcpy,
|
||||
runestrncpy,
|
||||
runestrecpy,
|
||||
runestrlen,
|
||||
runestrchr,
|
||||
runestrrchr,
|
||||
runestrdup,
|
||||
runestrstr \- rune string operations
|
||||
.SH SYNOPSIS
|
||||
.B #include <utf.h>
|
||||
.PP
|
||||
.ta \w'\fLRune* \fP'u
|
||||
.B
|
||||
Rune* runestrcat(Rune *s1, Rune *s2)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrncat(Rune *s1, Rune *s2, long n)
|
||||
.PP
|
||||
.B
|
||||
int runestrcmp(Rune *s1, Rune *s2)
|
||||
.PP
|
||||
.B
|
||||
int runestrncmp(Rune *s1, Rune *s2, long n)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrcpy(Rune *s1, Rune *s2)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrncpy(Rune *s1, Rune *s2, long n)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrecpy(Rune *s1, Rune *es1, Rune *s2)
|
||||
.PP
|
||||
.B
|
||||
long runestrlen(Rune *s)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrchr(Rune *s, Rune c)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrrchr(Rune *s, Rune c)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrdup(Rune *s)
|
||||
.PP
|
||||
.B
|
||||
Rune* runestrstr(Rune *s1, Rune *s2)
|
||||
.SH DESCRIPTION
|
||||
These functions are rune string analogues of
|
||||
the corresponding functions in
|
||||
.IR strcat (3).
|
||||
.SH HISTORY
|
||||
These routines first appeared in Plan 9.
|
||||
.SH SEE ALSO
|
||||
.IR memmove (3),
|
||||
.IR rune (3),
|
||||
.IR strcat (2)
|
||||
.SH BUGS
|
||||
The outcome of overlapping moves varies among implementations.
|
||||
576
man/man3/thread.3
Normal file
576
man/man3/thread.3
Normal file
@@ -0,0 +1,576 @@
|
||||
.TH THREAD 2
|
||||
.SH NAME
|
||||
alt,
|
||||
chancreate,
|
||||
chanfree,
|
||||
chaninit,
|
||||
chanprint,
|
||||
mainstacksize,
|
||||
proccreate,
|
||||
procdata,
|
||||
procexec,
|
||||
procexecl,
|
||||
procrfork,
|
||||
recv,
|
||||
recvp,
|
||||
recvul,
|
||||
send,
|
||||
sendp,
|
||||
sendul,
|
||||
nbrecv,
|
||||
nbrecvp,
|
||||
nbrecvul,
|
||||
nbsend,
|
||||
nbsendp,
|
||||
nbsendul,
|
||||
threadcreate,
|
||||
threaddata,
|
||||
threadexits,
|
||||
threadexitsall,
|
||||
threadgetgrp,
|
||||
threadgetname,
|
||||
threadint,
|
||||
threadintgrp,
|
||||
threadkill,
|
||||
threadkillgrp,
|
||||
threadmain,
|
||||
threadnotify,
|
||||
threadid,
|
||||
threadpid,
|
||||
threadsetgrp,
|
||||
threadsetname,
|
||||
threadwaitchan,
|
||||
yield \- thread and proc management
|
||||
.SH SYNOPSIS
|
||||
.PP
|
||||
.EX
|
||||
.ta 4n +4n +4n +4n +4n +4n +4n
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
.sp
|
||||
#define CHANEND 0
|
||||
#define CHANSND 1
|
||||
#define CHANRCV 2
|
||||
#define CHANNOP 3
|
||||
#define CHANNOBLK 4
|
||||
.sp
|
||||
.ta \w' 'u +\w'Channel 'u
|
||||
typedef struct Alt Alt;
|
||||
struct Alt {
|
||||
Channel *c;
|
||||
void *v;
|
||||
int op;
|
||||
Channel **tag;
|
||||
int entryno;
|
||||
};
|
||||
.fi
|
||||
.de XX
|
||||
.ift .sp 0.5
|
||||
.ifn .sp
|
||||
..
|
||||
.PP
|
||||
.nf
|
||||
.ft L
|
||||
.ta \w'\fLChannel* 'u +4n +4n +4n +4n
|
||||
void threadmain(int argc, char *argv[])
|
||||
int mainstacksize
|
||||
int proccreate(void (*fn)(void*), void *arg, uint stacksize)
|
||||
int procrfork(void (*fn)(void*), void *arg, uint stacksize,
|
||||
int rforkflag)
|
||||
int threadcreate(void (*fn)(void*), void *arg, uint stacksize)
|
||||
void threadexits(char *status)
|
||||
void threadexitsall(char *status)
|
||||
void yield(void)
|
||||
.XX
|
||||
int threadid(void)
|
||||
int threadgrp(void)
|
||||
int threadsetgrp(int group)
|
||||
int threadpid(int id)
|
||||
.XX
|
||||
int threadint(int id)
|
||||
int threadintgrp(int group)
|
||||
int threadkill(int id)
|
||||
int threadkillgrp(int group)
|
||||
.XX
|
||||
void threadsetname(char *name)
|
||||
char* threadgetname(void)
|
||||
.XX
|
||||
void** threaddata(void)
|
||||
void** procdata(void)
|
||||
.XX
|
||||
int chaninit(Channel *c, int elsize, int nel)
|
||||
Channel* chancreate(int elsize, int nel)
|
||||
void chanfree(Channel *c)
|
||||
.XX
|
||||
int alt(Alt *alts)
|
||||
int recv(Channel *c, void *v)
|
||||
void* recvp(Channel *c)
|
||||
ulong recvul(Channel *c)
|
||||
int nbrecv(Channel *c, void *v)
|
||||
void* nbrecvp(Channel *c)
|
||||
ulong nbrecvul(Channel *c)
|
||||
int send(Channel *c, void *v)
|
||||
int sendp(Channel *c, void *v)
|
||||
int sendul(Channel *c, ulong v)
|
||||
int nbsend(Channel *c, void *v)
|
||||
int nbsendp(Channel *c, void *v)
|
||||
int nbsendul(Channel *c, ulong v)
|
||||
int chanprint(Channel *c, char *fmt, ...)
|
||||
.XX
|
||||
int procexecl(Channel *cpid, char *file, ...)
|
||||
int procexec(Channel *cpid, char *file, char *args[])
|
||||
Channel* threadwaitchan(void)
|
||||
.XX
|
||||
int threadnotify(int (*f)(void*, char*), int in)
|
||||
.EE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The thread library provides parallel programming support similar to that
|
||||
of the languages
|
||||
Alef and Newsqueak.
|
||||
Threads
|
||||
and
|
||||
procs
|
||||
occupy a shared address space,
|
||||
communicating and synchronizing through
|
||||
.I channels
|
||||
and shared variables.
|
||||
.PP
|
||||
A
|
||||
.I proc
|
||||
is a Plan 9 process that contains one or more cooperatively scheduled
|
||||
.IR threads .
|
||||
Programs using threads must replace
|
||||
.I main
|
||||
by
|
||||
.IR threadmain .
|
||||
The thread library provides a
|
||||
.I main
|
||||
function that sets up a proc with a single thread executing
|
||||
.I threadmain
|
||||
on a stack of size
|
||||
.I mainstacksize
|
||||
(default eight kilobytes).
|
||||
To set
|
||||
.IR mainstacksize ,
|
||||
declare a global variable
|
||||
initialized to the desired value
|
||||
.RI ( e.g. ,
|
||||
.B int
|
||||
.B mainstacksize
|
||||
.B =
|
||||
.BR 1024 ).
|
||||
.PP
|
||||
.I Threadcreate
|
||||
creates a new thread in the calling proc, returning a unique integer
|
||||
identifying the thread; the thread
|
||||
executes
|
||||
.I fn(arg)
|
||||
on a stack of size
|
||||
.IR stacksize .
|
||||
Thread stacks are allocated in shared memory, making it valid to pass
|
||||
pointers to stack variables between threads and procs.
|
||||
.I Procrfork
|
||||
creates a new proc, and inside that proc creates
|
||||
a single thread as
|
||||
.I threadcreate
|
||||
would,
|
||||
returning the id of the created thread.
|
||||
.I Procrfork
|
||||
creates the new proc by calling
|
||||
.B rfork
|
||||
(see
|
||||
.IR fork (2))
|
||||
with flags
|
||||
.BR RFPROC|RFMEM|RFNOWAIT| \fIrforkflag\fR.
|
||||
(The thread library depends on all its procs
|
||||
running in the same rendezvous group.
|
||||
Do not include
|
||||
.B RFREND
|
||||
in
|
||||
.IR rforkflag .)
|
||||
.I Proccreate
|
||||
is identical to
|
||||
.I procrfork
|
||||
with
|
||||
.I rforkflag
|
||||
set to zero.
|
||||
Be aware that the calling thread may continue
|
||||
execution before
|
||||
the newly created proc and thread
|
||||
are scheduled.
|
||||
Because of this,
|
||||
.I arg
|
||||
should not point to data on the stack of a function that could
|
||||
return before the new process is scheduled.
|
||||
.PP
|
||||
.I Threadexits
|
||||
terminates the calling thread.
|
||||
If the thread is the last in its proc,
|
||||
.I threadexits
|
||||
also terminates the proc, using
|
||||
.I status
|
||||
as the exit status.
|
||||
.I Threadexitsall
|
||||
terminates all procs in the program,
|
||||
using
|
||||
.I status
|
||||
as the exit status.
|
||||
.PP
|
||||
The threads in a proc are coroutines, scheduled nonpreemptively
|
||||
in a round-robin fashion.
|
||||
A thread must explicitly relinquish control of the processor
|
||||
before another thread in the same proc is run.
|
||||
Calls that do this are
|
||||
.IR yield ,
|
||||
.IR proccreate ,
|
||||
.IR procexec ,
|
||||
.IR procexecl ,
|
||||
.IR threadexits ,
|
||||
.IR alt ,
|
||||
.IR send ,
|
||||
and
|
||||
.I recv
|
||||
(and the calls related to
|
||||
.I send
|
||||
and
|
||||
.IR recv \(emsee
|
||||
their descriptions further on).
|
||||
Procs are scheduled by the operating system.
|
||||
Therefore, threads in different procs can preempt one another
|
||||
in arbitrary ways and should synchronize their
|
||||
actions using
|
||||
.B qlocks
|
||||
(see
|
||||
.IR lock (2))
|
||||
or channel communication.
|
||||
System calls such as
|
||||
.IR read (2)
|
||||
block the entire proc;
|
||||
all threads in a proc block until the system call finishes.
|
||||
.PP
|
||||
As mentioned above, each thread has a unique integer thread id.
|
||||
Thread ids are not reused; they are unique across the life of the program.
|
||||
.I Threadid
|
||||
returns the id for the current thread.
|
||||
Each thread also has a thread group id.
|
||||
The initial thread has a group id of zero.
|
||||
Each new thread inherits the group id of
|
||||
the thread that created it.
|
||||
.I Threadgrp
|
||||
returns the group id for the current thread;
|
||||
.I threadsetgrp
|
||||
sets it.
|
||||
.I Threadpid
|
||||
returns the pid of the Plan 9 process containing
|
||||
the thread identified by
|
||||
.IR id ,
|
||||
or \-1
|
||||
if no such thread is found.
|
||||
.PP
|
||||
.I Threadint
|
||||
interrupts a thread that is blocked in a channel operation
|
||||
or system call.
|
||||
.I Threadintgrp
|
||||
interrupts all threads with the given group id.
|
||||
.I Threadkill
|
||||
marks a thread to die when it next relinquishes the processor
|
||||
(via one of the calls listed above).
|
||||
If the thread is blocked in a channel operation or system call,
|
||||
it is also interrupted.
|
||||
.I Threadkillgrp
|
||||
kills all threads with the given group id.
|
||||
Note that
|
||||
.I threadkill
|
||||
and
|
||||
.I threadkillgrp
|
||||
will not terminate a thread that never relinquishes
|
||||
the processor.
|
||||
.PP
|
||||
Primarily for debugging,
|
||||
threads can have string names associated with them.
|
||||
.I Threadgetname
|
||||
returns the current thread's name;
|
||||
.I threadsetname
|
||||
sets it.
|
||||
The pointer returned by
|
||||
.I threadgetname
|
||||
is only valid until the next call to
|
||||
.IR threadsetname .
|
||||
.PP
|
||||
.I Threaddata
|
||||
returns a pointer to a per-thread pointer
|
||||
that may be modified by threaded programs for
|
||||
per-thread storage.
|
||||
Similarly,
|
||||
.I procdata
|
||||
returns a pointer to a per-proc pointer.
|
||||
.PP
|
||||
.I Procexecl
|
||||
and
|
||||
.I procexec
|
||||
are threaded analogues of
|
||||
.I exec
|
||||
and
|
||||
.I execl
|
||||
(see
|
||||
.IR exec (2));
|
||||
on success,
|
||||
they replace the calling thread (which must be the only thread in its proc)
|
||||
and invoke the external program, never returning.
|
||||
On error, they return \-1.
|
||||
If
|
||||
.I cpid
|
||||
is not null, the pid of the invoked program
|
||||
will be sent along
|
||||
.I cpid
|
||||
once the program has been started, or \-1 will be sent if an
|
||||
error occurs.
|
||||
.I Procexec
|
||||
and
|
||||
.I procexecl
|
||||
will not access their arguments after sending a result
|
||||
along
|
||||
.IR cpid .
|
||||
Thus, programs that malloc the
|
||||
.I argv
|
||||
passed to
|
||||
.I procexec
|
||||
can safely free it once they have
|
||||
received the
|
||||
.I cpid
|
||||
response.
|
||||
.I Threadwaitchan
|
||||
returns a channel of pointers to
|
||||
.B Waitmsg
|
||||
structures (see
|
||||
.IR wait (2)).
|
||||
When an exec'ed process exits, a pointer to a
|
||||
.B Waitmsg
|
||||
is sent to this channel.
|
||||
These
|
||||
.B Waitmsg
|
||||
structures have been allocated with
|
||||
.IR malloc (2)
|
||||
and should be freed after use.
|
||||
.PP
|
||||
A
|
||||
.B Channel
|
||||
is a buffered or unbuffered queue for fixed-size messages.
|
||||
Procs and threads
|
||||
.I send
|
||||
messages into the channel and
|
||||
.I recv
|
||||
messages from the channel. If the channel is unbuffered, a
|
||||
.I send
|
||||
operation blocks until the corresponding
|
||||
.I recv
|
||||
operation occurs and
|
||||
.IR "vice versa" .
|
||||
.I Chaninit
|
||||
initializes a
|
||||
.B Channel
|
||||
for messages of size
|
||||
.I elsize
|
||||
and with a buffer holding
|
||||
.I nel
|
||||
messages.
|
||||
If
|
||||
.I nel
|
||||
is zero, the channel is unbuffered.
|
||||
.IR Chancreate
|
||||
allocates a new channel and initializes it.
|
||||
.I Chanfree
|
||||
frees a channel that is no longer used.
|
||||
.I Chanfree
|
||||
can be called by either sender or receiver after the last item has been
|
||||
sent or received. Freeing the channel will be delayed if there is a thread
|
||||
blocked on it until that thread unblocks (but
|
||||
.I chanfree
|
||||
returns immediately).
|
||||
.PP
|
||||
.I Send
|
||||
sends the element pointed at by
|
||||
.I v
|
||||
to the channel
|
||||
.IR c .
|
||||
If
|
||||
.I v
|
||||
is null, zeros are sent.
|
||||
.I Recv
|
||||
receives an element from
|
||||
.I c
|
||||
and stores it in
|
||||
.IR v .
|
||||
If
|
||||
.I v
|
||||
is null,
|
||||
the received value is discarded.
|
||||
.I Send
|
||||
and
|
||||
.I recv
|
||||
return 1 on success, \-1 if interrupted.
|
||||
.I Nbsend
|
||||
and
|
||||
.I nbrecv
|
||||
behave similarly, but return 0 rather than blocking.
|
||||
.PP
|
||||
.IR Sendp ,
|
||||
.IR nbsendp ,
|
||||
.IR sendul ,
|
||||
and
|
||||
.I nbsendul
|
||||
send a pointer or an unsigned long; the channel must
|
||||
have been initialized with the appropriate
|
||||
.IR elsize .
|
||||
.IR Recvp ,
|
||||
.IR nbrecvp ,
|
||||
.IR recvul ,
|
||||
and
|
||||
.I nbrecvul
|
||||
receive a pointer or an unsigned long;
|
||||
they return zero when a zero is received,
|
||||
when interrupted, or
|
||||
(for
|
||||
.I nbrecvp
|
||||
and
|
||||
.IR nbrecvul )
|
||||
when the operation would have blocked.
|
||||
To distinguish between these three cases,
|
||||
use
|
||||
.I recv
|
||||
or
|
||||
.IR nbrecv .
|
||||
.PP
|
||||
.I Alt
|
||||
can be used to recv from or send to one of a number of channels,
|
||||
as directed by an array of
|
||||
.B Alt
|
||||
structures,
|
||||
each of which describes a potential send or receive operation.
|
||||
In an
|
||||
.B Alt
|
||||
structure,
|
||||
.B c
|
||||
is the channel;
|
||||
.B v
|
||||
the value pointer (which may be null); and
|
||||
.B op
|
||||
the operation:
|
||||
.B CHANSND
|
||||
for a send operation,
|
||||
.B CHANRECV
|
||||
for a recv operation;
|
||||
.B CHANNOP
|
||||
for no operation
|
||||
(useful
|
||||
when
|
||||
.I alt
|
||||
is called with a varying set of operations).
|
||||
The array of
|
||||
.B Alt
|
||||
structures is terminated by an entry with
|
||||
.I op
|
||||
.B CHANEND
|
||||
or
|
||||
.BR CHANNOBLK .
|
||||
If at least one
|
||||
.B Alt
|
||||
structure can proceed, one of them is
|
||||
chosen at random to be executed.
|
||||
.I Alt
|
||||
returns the index of the chosen structure.
|
||||
If no operations can proceed and the list is terminated with
|
||||
.BR CHANNOBLK ,
|
||||
.I alt
|
||||
returns the index of the terminating
|
||||
.B CHANNOBLK
|
||||
structure.
|
||||
Otherwise,
|
||||
.I alt
|
||||
blocks until one of the operations can proceed,
|
||||
eventually returning the index of the structure executes.
|
||||
.I Alt
|
||||
returns \-1 when interrupted.
|
||||
The
|
||||
.B tag
|
||||
and
|
||||
.B entryno
|
||||
fields in the
|
||||
.B Alt
|
||||
structure are used internally by
|
||||
.I alt
|
||||
and need not be initialized.
|
||||
They are not used between
|
||||
.I alt
|
||||
calls.
|
||||
.PP
|
||||
.I Chanprint
|
||||
formats its arguments in the manner of
|
||||
.IR print (2)
|
||||
and sends the result to the channel
|
||||
.IR c.
|
||||
The string delivered by
|
||||
.I chanprint
|
||||
is allocated with
|
||||
.IR malloc (2)
|
||||
and should be freed upon receipt.
|
||||
.PP
|
||||
Thread library functions do not return on failure;
|
||||
if errors occur, the entire program is aborted.
|
||||
.PP
|
||||
Threaded programs should use
|
||||
.I threadnotify
|
||||
in place of
|
||||
.I atnotify
|
||||
(see
|
||||
.IR notify (2)).
|
||||
.PP
|
||||
It is safe to use
|
||||
.B sysfatal
|
||||
(see
|
||||
.IR perror (2))
|
||||
in threaded programs.
|
||||
.I Sysfatal
|
||||
will print the error string and call
|
||||
.IR threadexitsall .
|
||||
.PP
|
||||
It is safe to use
|
||||
.IR rfork
|
||||
(see
|
||||
.IR fork (2))
|
||||
to manage the namespace, file descriptors, note group, and environment of a
|
||||
single process.
|
||||
That is, it is safe to call
|
||||
.I rfork
|
||||
with the flags
|
||||
.BR RFNAMEG ,
|
||||
.BR RFFDG ,
|
||||
.BR RFCFDG ,
|
||||
.BR RFNOTEG ,
|
||||
.BR RFENVG ,
|
||||
and
|
||||
.BR RFCENVG.
|
||||
(To create new processes, use
|
||||
.I proccreate
|
||||
and
|
||||
.IR procrfork .)
|
||||
As mentioned above,
|
||||
the thread library depends on all procs being in the
|
||||
same rendezvous group; do not change the rendezvous
|
||||
group with
|
||||
.IR rfork .
|
||||
.SH FILES
|
||||
.B /sys/lib/acid/thread
|
||||
contains useful
|
||||
.IR acid (1)
|
||||
functions for debugging threaded programs.
|
||||
.PP
|
||||
.B /sys/src/libthread/example.c
|
||||
contains a full example program.
|
||||
.SH SOURCE
|
||||
.B /sys/src/libthread
|
||||
.SH SEE ALSO
|
||||
.IR intro (2),
|
||||
.IR ioproc (2)
|
||||
19
package
Executable file
19
package
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf ../9tmp
|
||||
mkdir ../9tmp
|
||||
mkdir ../9pkg
|
||||
cp -R * ../9tmp
|
||||
cd ../9tmp
|
||||
rm -rf `find . -name CVS`
|
||||
rm lib/*
|
||||
rm */*.o
|
||||
rm */*.a
|
||||
rm mk/mk
|
||||
rm sam/sam
|
||||
rm man/*/*
|
||||
for i in libfmt libbio lib9 libthread libutf libregexp sam mk
|
||||
do
|
||||
tar cf - $i |gzip >../9pkg/$i.tar.gz
|
||||
done
|
||||
tar cf - . | gzip > ../9pkg/all.tar.gz
|
||||
258
src/lib9/LICENSE
Normal file
258
src/lib9/LICENSE
Normal file
@@ -0,0 +1,258 @@
|
||||
The Plan 9 software is provided under the terms of the
|
||||
Lucent Public License, Version 1.02, reproduced below,
|
||||
with the following exceptions:
|
||||
|
||||
1. No right is granted to create derivative works of or
|
||||
to redistribute (other than with the Plan 9 Operating System)
|
||||
the screen imprinter fonts identified in subdirectory
|
||||
/lib/font/bit/lucida and printer fonts (Lucida Sans Unicode, Lucida
|
||||
Sans Italic, Lucida Sans Demibold, Lucida Typewriter, Lucida Sans
|
||||
Typewriter83), identified in subdirectory /sys/lib/postscript/font.
|
||||
These directories contain material copyrights by B&H Inc. and Y&Y Inc.
|
||||
|
||||
2. The printer fonts identified in subdirectory /sys/lib/ghostscript/font
|
||||
are subject to the GNU GPL, reproduced in the file /LICENSE.gpl.
|
||||
|
||||
3. The ghostscript program in the subdirectory /sys/src/cmd/gs is
|
||||
covered by the Aladdin Free Public License, reproduced in the file
|
||||
/LICENSE.afpl.
|
||||
|
||||
===================================================================
|
||||
|
||||
Lucent Public License Version 1.02
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
|
||||
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
|
||||
PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
|
||||
Program, and
|
||||
b. in the case of each Contributor,
|
||||
|
||||
i. changes to the Program, and
|
||||
ii. additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program were added to the
|
||||
Program by such Contributor itself or anyone acting on such
|
||||
Contributor's behalf, and the Contributor explicitly consents, in
|
||||
accordance with Section 3C, to characterization of the changes and/or
|
||||
additions as Contributions.
|
||||
|
||||
"Contributor" means LUCENT and any other entity that has Contributed a
|
||||
Contribution to the Program.
|
||||
|
||||
"Distributor" means a Recipient that distributes the Program,
|
||||
modifications to the Program, or any part thereof.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor
|
||||
which are necessarily infringed by the use or sale of its Contribution
|
||||
alone or when combined with the Program.
|
||||
|
||||
"Original Program" means the original version of the software
|
||||
accompanying this Agreement as released by LUCENT, including source
|
||||
code, object code and documentation, if any.
|
||||
|
||||
"Program" means the Original Program and Contributions or any part
|
||||
thereof
|
||||
|
||||
"Recipient" means anyone who receives the Program under this
|
||||
Agreement, including all Contributors.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare derivative works of, publicly display,
|
||||
publicly perform, distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such derivative works, in source code and
|
||||
object code form.
|
||||
|
||||
b. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor, if
|
||||
any, in source code and object code form. The patent license granted
|
||||
by a Contributor shall also apply to the combination of the
|
||||
Contribution of that Contributor and the Program if, at the time the
|
||||
Contribution is added by the Contributor, such addition of the
|
||||
Contribution causes such combination to be covered by the Licensed
|
||||
Patents. The patent license granted by a Contributor shall not apply
|
||||
to (i) any other combinations which include the Contribution, nor to
|
||||
(ii) Contributions of other Contributors. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c. Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity. Each
|
||||
Contributor disclaims any liability to Recipient for claims brought by
|
||||
any other entity based on infringement of intellectual property rights
|
||||
or otherwise. As a condition to exercising the rights and licenses
|
||||
granted hereunder, each Recipient hereby assumes sole responsibility
|
||||
to secure any other intellectual property rights needed, if any. For
|
||||
example, if a third party patent license is required to allow
|
||||
Recipient to distribute the Program, it is Recipient's responsibility
|
||||
to acquire that license before distributing the Program.
|
||||
|
||||
d. Each Contributor represents that to its knowledge it has sufficient
|
||||
copyright rights in its Contribution, if any, to grant the copyright
|
||||
license set forth in this Agreement.
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A. Distributor may choose to distribute the Program in any form under
|
||||
this Agreement or under its own license agreement, provided that:
|
||||
|
||||
a. it complies with the terms and conditions of this Agreement;
|
||||
|
||||
b. if the Program is distributed in source code or other tangible
|
||||
form, a copy of this Agreement or Distributor's own license agreement
|
||||
is included with each copy of the Program; and
|
||||
|
||||
c. if distributed under Distributor's own license agreement, such
|
||||
license agreement:
|
||||
|
||||
i. effectively disclaims on behalf of all Contributors all warranties
|
||||
and conditions, express and implied, including warranties or
|
||||
conditions of title and non-infringement, and implied warranties or
|
||||
conditions of merchantability and fitness for a particular purpose;
|
||||
ii. effectively excludes on behalf of all Contributors all liability
|
||||
for damages, including direct, indirect, special, incidental and
|
||||
consequential damages, such as lost profits; and
|
||||
iii. states that any provisions which differ from this Agreement are
|
||||
offered by that Contributor alone and not by any other party.
|
||||
|
||||
B. Each Distributor must include the following in a conspicuous
|
||||
location in the Program:
|
||||
|
||||
Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
|
||||
Reserved.
|
||||
|
||||
C. In addition, each Contributor must identify itself as the
|
||||
originator of its Contribution in a manner that reasonably allows
|
||||
subsequent Recipients to identify the originator of the Contribution.
|
||||
Also, each Contributor must agree that the additions and/or changes
|
||||
are intended to be a Contribution. Once a Contribution is contributed,
|
||||
it may not thereafter be revoked.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain
|
||||
responsibilities with respect to end users, business partners and the
|
||||
like. While this license is intended to facilitate the commercial use
|
||||
of the Program, the Distributor who includes the Program in a
|
||||
commercial product offering should do so in a manner which does not
|
||||
create potential liability for Contributors. Therefore, if a
|
||||
Distributor includes the Program in a commercial product offering,
|
||||
such Distributor ("Commercial Distributor") hereby agrees to defend
|
||||
and indemnify every Contributor ("Indemnified Contributor") against
|
||||
any losses, damages and costs (collectively"Losses") arising from
|
||||
claims, lawsuits and other legal actions brought by a third party
|
||||
against the Indemnified Contributor to the extent caused by the acts
|
||||
or omissions of such Commercial Distributor in connection with its
|
||||
distribution of the Program in a commercial product offering. The
|
||||
obligations in this section do not apply to any claims or Losses
|
||||
relating to any actual or alleged intellectual property infringement.
|
||||
In order to qualify, an Indemnified Contributor must: a) promptly
|
||||
notify the Commercial Distributor in writing of such claim, and b)
|
||||
allow the Commercial Distributor to control, and cooperate with the
|
||||
Commercial Distributor in, the defense and any related settlement
|
||||
negotiations. The Indemnified Contributor may participate in any such
|
||||
claim at its own expense.
|
||||
|
||||
For example, a Distributor might include the Program in a commercial
|
||||
product offering, Product X. That Distributor is then a Commercial
|
||||
Distributor. If that Commercial Distributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Distributor's responsibility
|
||||
alone. Under this section, the Commercial Distributor would have to
|
||||
defend claims against the Contributors related to those performance
|
||||
claims and warranties, and if a court requires any Contributor to pay
|
||||
any damages as a result, the Commercial Distributor must pay those
|
||||
damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
|
||||
PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and
|
||||
distributing the Program and assumes all risks associated with its
|
||||
exercise of rights under this Agreement, including but not limited to
|
||||
the risks and costs of program errors, compliance with applicable
|
||||
laws, damage to or loss of data, programs or equipment, and
|
||||
unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
|
||||
ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
|
||||
WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
|
||||
DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. EXPORT CONTROL
|
||||
|
||||
Recipient agrees that Recipient alone is responsible for compliance
|
||||
with the United States export administration regulations (and the
|
||||
export control laws and regulation of any other countries).
|
||||
|
||||
8. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against a Contributor with
|
||||
respect to a patent applicable to software (including a cross-claim or
|
||||
counterclaim in a lawsuit), then any patent licenses granted by that
|
||||
Contributor to such Recipient under this Agreement shall terminate as
|
||||
of the date such litigation is filed. In addition, if Recipient
|
||||
institutes patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Program
|
||||
itself (excluding combinations of the Program with other software or
|
||||
hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and
|
||||
survive.
|
||||
|
||||
LUCENT may publish new versions (including revisions) of this
|
||||
Agreement from time to time. Each new version of the Agreement will be
|
||||
given a distinguishing version number. The Program (including
|
||||
Contributions) may always be distributed subject to the version of the
|
||||
Agreement under which it was received. In addition, after a new
|
||||
version of the Agreement is published, Contributor may elect to
|
||||
distribute the Program (including its Contributions) under the new
|
||||
version. No one other than LUCENT has the right to modify this
|
||||
Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
|
||||
Recipient receives no rights or licenses to the intellectual property
|
||||
of any Contributor under this Agreement, whether expressly, by
|
||||
implication, estoppel or otherwise. All rights in the Program not
|
||||
expressly granted under this Agreement are reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and
|
||||
the intellectual property laws of the United States of America. No
|
||||
party to this Agreement will bring a legal action under this Agreement
|
||||
more than one year after the cause of action arose. Each party waives
|
||||
its rights to a jury trial in any resulting litigation.
|
||||
|
||||
6
src/lib9/Make.Darwin-PowerMacintosh
Normal file
6
src/lib9/Make.Darwin-PowerMacintosh
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I${PREFIX}/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.FreeBSD-386
Normal file
7
src/lib9/Make.FreeBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.HP-UX-9000
Normal file
6
src/lib9/Make.HP-UX-9000
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS=-O -c -Ae -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.Linux-386
Normal file
7
src/lib9/Make.Linux-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.NetBSD-386
Normal file
7
src/lib9/Make.NetBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.OSF1-alpha
Normal file
6
src/lib9/Make.OSF1-alpha
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
2
src/lib9/Make.SunOS-sun4u
Normal file
2
src/lib9/Make.SunOS-sun4u
Normal file
@@ -0,0 +1,2 @@
|
||||
include Make.SunOS-sun4u-$(CC)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.SunOS-sun4u-cc
Normal file
6
src/lib9/Make.SunOS-sun4u-cc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I. -O
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.SunOS-sun4u-gcc
Normal file
6
src/lib9/Make.SunOS-sun4u-gcc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
120
src/lib9/Makefile
Normal file
120
src/lib9/Makefile
Normal file
@@ -0,0 +1,120 @@
|
||||
|
||||
# this works in gnu make
|
||||
SYSNAME:=${shell uname}
|
||||
OBJTYPE:=${shell uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'}
|
||||
|
||||
# this works in bsd make
|
||||
SYSNAME!=uname
|
||||
OBJTYPE!=uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'
|
||||
|
||||
# the gnu rules will mess up bsd but not vice versa,
|
||||
# hence the gnu rules come first.
|
||||
|
||||
include Make.$(SYSNAME)-$(OBJTYPE)
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
NUKEFILES=
|
||||
|
||||
TGZFILES=
|
||||
|
||||
LIB=lib9.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/lib9
|
||||
NAME=lib9
|
||||
|
||||
OFILES=\
|
||||
_exits.$O\
|
||||
argv0.$O\
|
||||
await.$O\
|
||||
encodefmt.$O\
|
||||
errstr.$O\
|
||||
exits.$O\
|
||||
ffork-$(SYSNAME).$O\
|
||||
getcallerpc-$(OBJTYPE).$O\
|
||||
getfields.$O\
|
||||
lock.$O\
|
||||
malloctag.$O\
|
||||
mallocz.$O\
|
||||
nrand.$O\
|
||||
qlock.$O\
|
||||
readn.$O\
|
||||
rendez.$O\
|
||||
strecpy.$O\
|
||||
sysfatal.$O\
|
||||
tas-$(OBJTYPE).$O\
|
||||
tokenize.$O\
|
||||
u16.$O\
|
||||
u32.$O\
|
||||
u64.$O\
|
||||
wait.$O\
|
||||
werrstr.$O\
|
||||
|
||||
HFILES=\
|
||||
lib9.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
# install -m 0644 lib9.3 $(PREFIX)/man/man3/lib9.3
|
||||
install -m 0644 lib9.h $(PREFIX)/include/lib9.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
testfork: $(LIB) testfork.$O
|
||||
$(CC) -o testfork testfork.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
$(AR) $(ARFLAGS) $(LIB) $(OFILES)
|
||||
|
||||
NUKEFILES+=$(LIB)
|
||||
.c.$O:
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
tgz:
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
mkdir $(NAME)-$(VERSION)
|
||||
cp Makefile Make.* README LICENSE NOTICE *.[ch137] rpm.spec bundle.ports $(TGZFILES) $(NAME)-$(VERSION)
|
||||
tar cf - $(NAME)-$(VERSION) | gzip >$(NAME)-$(VERSION).tgz
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES) $(LIB)
|
||||
|
||||
nuke:
|
||||
rm -f $(OFILES) *.tgz *.rpm $(NUKEFILES)
|
||||
|
||||
rpm:
|
||||
make tgz
|
||||
cp $(NAME)-$(VERSION).tgz /usr/src/RPM/SOURCES
|
||||
rpm -ba rpm.spec
|
||||
cp /usr/src/RPM/SRPMS/$(NAME)-$(VERSION)-1.src.rpm .
|
||||
cp /usr/src/RPM/RPMS/i586/$(NAME)-$(VERSION)-1.i586.rpm .
|
||||
scp *.rpm rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
PORTDIR=/usr/ports/$(PORTPLACE)
|
||||
|
||||
ports:
|
||||
make tgz
|
||||
rm -rf $(PORTDIR)
|
||||
mkdir $(PORTDIR)
|
||||
cp $(NAME)-$(VERSION).tgz /usr/ports/distfiles
|
||||
cat bundle.ports | (cd $(PORTDIR) && awk '$$1=="---" && $$3=="---" { ofile=$$2; next} {if(ofile) print >ofile}')
|
||||
(cd $(PORTDIR); make makesum)
|
||||
(cd $(PORTDIR); make)
|
||||
(cd $(PORTDIR); /usr/local/bin/portlint)
|
||||
rm -rf $(PORTDIR)/work
|
||||
shar `find $(PORTDIR)` > ports.shar
|
||||
(cd $(PORTDIR); tar cf - *) | gzip >$(NAME)-$(VERSION)-ports.tgz
|
||||
scp *.tgz rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
.phony: all clean nuke install tgz rpm ports
|
||||
49
src/lib9/Makefile.MID
Normal file
49
src/lib9/Makefile.MID
Normal file
@@ -0,0 +1,49 @@
|
||||
LIB=lib9.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/lib9
|
||||
NAME=lib9
|
||||
|
||||
OFILES=\
|
||||
_exits.$O\
|
||||
argv0.$O\
|
||||
await.$O\
|
||||
encodefmt.$O\
|
||||
errstr.$O\
|
||||
exits.$O\
|
||||
ffork-$(SYSNAME).$O\
|
||||
getcallerpc-$(OBJTYPE).$O\
|
||||
getfields.$O\
|
||||
lock.$O\
|
||||
malloctag.$O\
|
||||
mallocz.$O\
|
||||
nrand.$O\
|
||||
qlock.$O\
|
||||
readn.$O\
|
||||
rendez.$O\
|
||||
strecpy.$O\
|
||||
sysfatal.$O\
|
||||
tas-$(OBJTYPE).$O\
|
||||
tokenize.$O\
|
||||
u16.$O\
|
||||
u32.$O\
|
||||
u64.$O\
|
||||
wait.$O\
|
||||
werrstr.$O\
|
||||
|
||||
HFILES=\
|
||||
lib9.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
# install -m 0644 lib9.3 $(PREFIX)/man/man3/lib9.3
|
||||
install -m 0644 lib9.h $(PREFIX)/include/lib9.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
testfork: $(LIB) testfork.$O
|
||||
$(CC) -o testfork testfork.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
9
src/lib9/_exits.c
Normal file
9
src/lib9/_exits.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
_exits(char *s)
|
||||
{
|
||||
if(s && *s)
|
||||
_exit(1);
|
||||
_exit(0);
|
||||
}
|
||||
4
src/lib9/argv0.c
Normal file
4
src/lib9/argv0.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <lib9.h>
|
||||
|
||||
char *argv0;
|
||||
|
||||
105
src/lib9/await.c
Normal file
105
src/lib9/await.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <lib9.h>
|
||||
|
||||
static struct {
|
||||
int sig;
|
||||
char *str;
|
||||
} tab[] = {
|
||||
SIGHUP, "hangup",
|
||||
SIGINT, "interrupt",
|
||||
SIGQUIT, "quit",
|
||||
SIGILL, "sys: trap: illegal instruction",
|
||||
SIGTRAP, "sys: trace trap",
|
||||
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",
|
||||
SIGIO, "sys: i/o possible on fd",
|
||||
SIGXCPU, "sys: cpu time limit exceeded",
|
||||
SIGXFSZ, "sys: file size limit exceeded",
|
||||
SIGVTALRM, "sys: virtual time alarm",
|
||||
SIGPROF, "sys: profiling timer alarm",
|
||||
SIGWINCH, "sys: window size change",
|
||||
#ifdef SIGINFO
|
||||
SIGINFO, "sys: status request",
|
||||
#endif
|
||||
SIGUSR1, "sys: usr1",
|
||||
SIGUSR2, "sys: usr2",
|
||||
};
|
||||
|
||||
static char*
|
||||
_p9sigstr(int sig, char *tmp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(tab); i++)
|
||||
if(tab[i].sig == sig)
|
||||
return tab[i].str;
|
||||
sprint(tmp, "sys: signal %d", sig);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
static 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;
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
await(char *str, int n)
|
||||
{
|
||||
int pid, status, cd;
|
||||
struct rusage ru;
|
||||
char buf[128], tmp[64];
|
||||
ulong u, s;
|
||||
|
||||
for(;;){
|
||||
pid = wait3(&status, 0, &ru);
|
||||
if(pid < 0)
|
||||
return -1;
|
||||
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);
|
||||
if(WIFEXITED(status)){
|
||||
status = WEXITSTATUS(status);
|
||||
if(status)
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu %d", pid, u, s, u+s, status);
|
||||
else
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu ''", pid, u, s, u+s);
|
||||
strecpy(str, str+n, buf);
|
||||
return strlen(str);
|
||||
}
|
||||
if(WIFSIGNALED(status)){
|
||||
cd = WCOREDUMP(status);
|
||||
USED(cd);
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu '%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp));
|
||||
strecpy(str, str+n, buf);
|
||||
return strlen(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/lib9/encodefmt.c
Normal file
69
src/lib9/encodefmt.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <lib9.h>
|
||||
|
||||
int
|
||||
encodefmt(Fmt *f)
|
||||
{
|
||||
char *out;
|
||||
char *buf;
|
||||
int len;
|
||||
int ilen;
|
||||
int rv;
|
||||
uchar *b;
|
||||
char obuf[64]; // rsc optimization
|
||||
|
||||
if(!(f->flags&FmtPrec) || f->prec < 1)
|
||||
goto error;
|
||||
|
||||
b = va_arg(f->args, uchar*);
|
||||
|
||||
ilen = f->prec;
|
||||
f->prec = 0;
|
||||
f->flags &= ~FmtPrec;
|
||||
switch(f->r){
|
||||
case '<':
|
||||
len = (8*ilen+4)/5 + 3;
|
||||
break;
|
||||
case '[':
|
||||
len = (8*ilen+5)/6 + 4;
|
||||
break;
|
||||
case 'H':
|
||||
len = 2*ilen + 1;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(len > sizeof(obuf)){
|
||||
buf = malloc(len);
|
||||
if(buf == nil)
|
||||
goto error;
|
||||
} else
|
||||
buf = obuf;
|
||||
|
||||
// convert
|
||||
out = buf;
|
||||
switch(f->r){
|
||||
case '<':
|
||||
rv = enc32(out, len, b, ilen);
|
||||
break;
|
||||
case '[':
|
||||
rv = enc64(out, len, b, ilen);
|
||||
break;
|
||||
case 'H':
|
||||
rv = enc16(out, len, b, ilen);
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
if(rv < 0)
|
||||
goto error;
|
||||
|
||||
fmtstrcpy(f, buf);
|
||||
if(buf != obuf)
|
||||
free(buf);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return fmtstrcpy(f, "<encodefmt>");
|
||||
}
|
||||
68
src/lib9/errstr.c
Normal file
68
src/lib9/errstr.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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 <errno.h>
|
||||
#include <string.h>
|
||||
#include <lib9.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;
|
||||
|
||||
syserr = getsyserr();
|
||||
if(errno != EPLAN9)
|
||||
strcpy(syserr, strerror(errno));
|
||||
|
||||
strecpy(tmp, tmp+ERRMAX, syserr);
|
||||
strecpy(syserr, syserr+ERRMAX, err);
|
||||
strecpy(err, err+n, tmp);
|
||||
errno = EPLAN9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rerrstr(char *err, uint n)
|
||||
{
|
||||
char *syserr;
|
||||
|
||||
syserr = getsyserr();
|
||||
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));
|
||||
}
|
||||
10
src/lib9/exits.c
Normal file
10
src/lib9/exits.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
exits(char *s)
|
||||
{
|
||||
if(s && *s)
|
||||
exit(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
33
src/lib9/ffork-FreeBSD.c
Normal file
33
src/lib9/ffork-FreeBSD.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <lib9.h>
|
||||
|
||||
extern int __isthreaded;
|
||||
int
|
||||
ffork(int flags, void(*fn)(void*), void *arg)
|
||||
{
|
||||
void *p;
|
||||
|
||||
__isthreaded = 1;
|
||||
p = malloc(16384);
|
||||
if(p == nil)
|
||||
return -1;
|
||||
memset(p, 0xFE, 16384);
|
||||
return rfork_thread(RFPROC|flags, (char*)p+16000, (int(*)(void*))fn, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* For FreeBSD libc.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
volatile long access_lock;
|
||||
volatile long lock_owner;
|
||||
volatile char *fname;
|
||||
volatile int lineno;
|
||||
} spinlock_t;
|
||||
|
||||
void
|
||||
_spinlock(spinlock_t *lk)
|
||||
{
|
||||
lock((Lock*)&lk->access_lock);
|
||||
}
|
||||
|
||||
39
src/lib9/ffork-Linux.c
Normal file
39
src/lib9/ffork-Linux.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <lib9.h>
|
||||
|
||||
int fforkstacksize = 16384;
|
||||
|
||||
int
|
||||
ffork(int flags, void (*fn)(void*), void *arg)
|
||||
{
|
||||
char *p;
|
||||
int cloneflag, pid;
|
||||
|
||||
p = malloc(fforkstacksize);
|
||||
if(p == nil)
|
||||
return -1;
|
||||
cloneflag = 0;
|
||||
flags &= ~RFPROC;
|
||||
if(flags&RFMEM){
|
||||
cloneflag |= CLONE_VM;
|
||||
flags &= ~RFMEM;
|
||||
}
|
||||
if(!(flags&RFFDG))
|
||||
cloneflag |= CLONE_FILES;
|
||||
else
|
||||
flags &= ~RFFDG;
|
||||
if(!(flags&RFNOWAIT))
|
||||
cloneflag |= SIGCHLD;
|
||||
else
|
||||
flags &= ~RFNOWAIT;
|
||||
if(flags){
|
||||
fprint(2, "unknown rfork flags %x\n", flags);
|
||||
return -1;
|
||||
}
|
||||
pid = clone((int(*)(void*))fn, p+fforkstacksize-16, cloneflag, arg);
|
||||
if(pid < 0)
|
||||
free(p);
|
||||
return pid;
|
||||
}
|
||||
|
||||
7
src/lib9/getcallerpc-386.c
Normal file
7
src/lib9/getcallerpc-386.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <lib9.h>
|
||||
|
||||
ulong
|
||||
getcallerpc(void *x)
|
||||
{
|
||||
return (((ulong*)(x))[-1]);
|
||||
}
|
||||
36
src/lib9/getfields.c
Normal file
36
src/lib9/getfields.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#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;
|
||||
}
|
||||
246
src/lib9/lib9.h
Normal file
246
src/lib9/lib9.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* 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 _LIB9H_
|
||||
#define _LIB9H_ 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _FMTH_
|
||||
# include <fmt.h>
|
||||
#endif
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
#define _NEEDUCHAR 1
|
||||
#define _NEEDUSHORT 1
|
||||
#define _NEEDUINT 1
|
||||
#define _NEEDULONG 1
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/types.h>
|
||||
# if defined(__USE_MISC)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# if !defined(_POSIX_SOURCE)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef signed char schar;
|
||||
typedef unsigned int u32int;
|
||||
#ifdef _NEEDUCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#ifdef _NEEDUSHORT
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
#ifdef _NEEDUINT
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#ifdef _NEEDULONG
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long long vlong;
|
||||
|
||||
/* rfork to create new process running fn(arg) */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef RFFDG
|
||||
#undef RFNOTEG
|
||||
#undef RFPROC
|
||||
#undef RFMEM
|
||||
#undef RFNOWAIT
|
||||
#undef RFCFDG
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/* RFNAMEG = (1<<0), */
|
||||
/* RFENVG = (1<<1), */
|
||||
RFFDG = (1<<2),
|
||||
RFNOTEG = (1<<3),
|
||||
RFPROC = (1<<4),
|
||||
RFMEM = (1<<5),
|
||||
RFNOWAIT = (1<<6),
|
||||
/* RFCNAMEG = (1<<10), */
|
||||
/* RFCENVG = (1<<11), */
|
||||
RFCFDG = (1<<12),
|
||||
/* RFREND = (1<<13), */
|
||||
/* RFNOMNT = (1<<14) */
|
||||
};
|
||||
extern int ffork(int, void(*)(void*), void*);
|
||||
|
||||
/* wait for processes */
|
||||
#define wait _p9wait
|
||||
typedef struct Waitmsg Waitmsg;
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
};
|
||||
extern int await(char*, int);
|
||||
extern Waitmsg* wait(void);
|
||||
|
||||
/* synchronization */
|
||||
typedef struct Lock Lock;
|
||||
struct Lock
|
||||
{
|
||||
int val;
|
||||
};
|
||||
|
||||
extern int _tas(void*);
|
||||
extern void lock(Lock*);
|
||||
extern void unlock(Lock*);
|
||||
extern int canlock(Lock*);
|
||||
|
||||
typedef struct QLp QLp;
|
||||
struct QLp
|
||||
{
|
||||
int inuse;
|
||||
QLp *next;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef struct QLock QLock;
|
||||
struct QLock
|
||||
{
|
||||
Lock lock;
|
||||
int locked;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void qlock(QLock*);
|
||||
extern void qunlock(QLock*);
|
||||
extern int canqlock(QLock*);
|
||||
extern void _qlockinit(ulong (*)(ulong, ulong));
|
||||
|
||||
typedef struct RWLock RWLock;
|
||||
struct RWLock
|
||||
{
|
||||
Lock lock;
|
||||
int readers;
|
||||
int writer;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rlock(RWLock*);
|
||||
extern void runlock(RWLock*);
|
||||
extern int canrlock(RWLock*);
|
||||
extern void wlock(RWLock*);
|
||||
extern void wunlock(RWLock*);
|
||||
extern int canwlock(RWLock*);
|
||||
|
||||
typedef struct Rendez Rendez;
|
||||
struct Rendez
|
||||
{
|
||||
QLock *l;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rsleep(Rendez*);
|
||||
extern int rwakeup(Rendez*);
|
||||
extern int rwakeupall(Rendez*);
|
||||
|
||||
extern ulong rendezvous(ulong, ulong);
|
||||
|
||||
/* one of a kind */
|
||||
extern void sysfatal(char*, ...);
|
||||
extern int nrand(int);
|
||||
extern void setmalloctag(void*, ulong);
|
||||
extern void setrealloctag(void*, ulong);
|
||||
extern void *mallocz(ulong, int);
|
||||
extern long readn(int, void*, long);
|
||||
extern void exits(char*);
|
||||
extern void _exits(char*);
|
||||
extern ulong getcallerpc(void*);
|
||||
|
||||
/* string routines */
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
extern int cistrncmp(char*, char*, int);
|
||||
extern int cistrcmp(char*, char*);
|
||||
extern char* cistrstr(char*, char*);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
extern int gettokens(char *, char **, int, char *);
|
||||
|
||||
/* formatting helpers */
|
||||
extern int dec64(uchar*, int, char*, int);
|
||||
extern int enc64(char*, int, uchar*, int);
|
||||
extern int dec32(uchar*, int, char*, int);
|
||||
extern int enc32(char*, int, uchar*, int);
|
||||
extern int dec16(uchar*, int, char*, int);
|
||||
extern int enc16(char*, int, uchar*, int);
|
||||
extern int encodefmt(Fmt*);
|
||||
|
||||
/* error string */
|
||||
enum
|
||||
{
|
||||
ERRMAX = 128
|
||||
};
|
||||
extern void rerrstr(char*, uint);
|
||||
extern void werrstr(char*, ...);
|
||||
extern int errstr(char*, uint);
|
||||
|
||||
/* compiler directives on plan 9 */
|
||||
#define USED(x) if(x){}else{}
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
/* command line */
|
||||
extern char *argv0;
|
||||
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
|
||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
||||
argc--, argv++) {\
|
||||
char *_args, *_argt;\
|
||||
Rune _argc;\
|
||||
_args = &argv[0][1];\
|
||||
if(_args[0]=='-' && _args[1]==0){\
|
||||
argc--; argv++; break;\
|
||||
}\
|
||||
_argc = 0;\
|
||||
while(*_args && (_args += chartorune(&_argc, _args)))\
|
||||
switch(_argc)
|
||||
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
|
||||
#define ARGF() (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
|
||||
#define EARGF(x) (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
|
||||
|
||||
#define ARGC() _argc
|
||||
|
||||
#define OREAD O_RDONLY
|
||||
#define OWRITE O_WRONLY
|
||||
#define AEXIST 0
|
||||
#define AREAD 4
|
||||
#define AWRITE 2
|
||||
#define AEXEC 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIB9H_ */
|
||||
54
src/lib9/lock.c
Normal file
54
src/lib9/lock.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <lib9.h>
|
||||
|
||||
int _ntas;
|
||||
static int
|
||||
_xtas(void *v)
|
||||
{
|
||||
int x;
|
||||
|
||||
_ntas++;
|
||||
x = _tas(v);
|
||||
if(x == 0 || x == 0xCAFEBABE)
|
||||
return x;
|
||||
fprint(2, "%d: tas %p got %ux\n", getpid(), v, x);
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
canlock(Lock *l)
|
||||
{
|
||||
return !_xtas(&l->val);
|
||||
}
|
||||
|
||||
void
|
||||
unlock(Lock *l)
|
||||
{
|
||||
l->val = 0;
|
||||
}
|
||||
|
||||
void
|
||||
lock(Lock *lk)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* once fast */
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
/* a thousand times pretty fast */
|
||||
for(i=0; i<1000; i++){
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
sched_yield();
|
||||
}
|
||||
/* now nice and slow */
|
||||
for(i=0; i<1000; i++){
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
usleep(100*1000);
|
||||
}
|
||||
/* take your time */
|
||||
while(_xtas(&lk->val))
|
||||
usleep(1000*1000);
|
||||
}
|
||||
15
src/lib9/malloctag.c
Normal file
15
src/lib9/malloctag.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
setmalloctag(void *v, ulong t)
|
||||
{
|
||||
USED(v);
|
||||
USED(t);
|
||||
}
|
||||
|
||||
void
|
||||
setrealloctag(void *v, ulong t)
|
||||
{
|
||||
USED(v);
|
||||
USED(t);
|
||||
}
|
||||
14
src/lib9/mallocz.c
Normal file
14
src/lib9/mallocz.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <lib9.h>
|
||||
|
||||
void*
|
||||
mallocz(unsigned long n, int clr)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = malloc(n);
|
||||
if(clr && v)
|
||||
memset(v, 0, n);
|
||||
return v;
|
||||
}
|
||||
2
src/lib9/mkfile
Normal file
2
src/lib9/mkfile
Normal file
@@ -0,0 +1,2 @@
|
||||
<../libutf/mkfile
|
||||
|
||||
17
src/lib9/nrand.c
Normal file
17
src/lib9/nrand.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <lib9.h>
|
||||
|
||||
#define MASK 0x7fffffffL
|
||||
|
||||
int
|
||||
nrand(int n)
|
||||
{
|
||||
long slop, v;
|
||||
|
||||
if(n < 0)
|
||||
return n;
|
||||
slop = MASK % n;
|
||||
do
|
||||
v = lrand();
|
||||
while(v <= slop);
|
||||
return v % n;
|
||||
}
|
||||
360
src/lib9/qlock.c
Normal file
360
src/lib9/qlock.c
Normal file
@@ -0,0 +1,360 @@
|
||||
#include <lib9.h>
|
||||
|
||||
static struct {
|
||||
QLp *p;
|
||||
QLp x[1024];
|
||||
} ql = {
|
||||
ql.x
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Queuing,
|
||||
QueuingR,
|
||||
QueuingW,
|
||||
Sleeping,
|
||||
};
|
||||
|
||||
static ulong (*_rendezvousp)(ulong, ulong) = rendezvous;
|
||||
|
||||
/* this gets called by the thread library ONLY to get us to use its rendezvous */
|
||||
void
|
||||
_qlockinit(ulong (*r)(ulong, ulong))
|
||||
{
|
||||
_rendezvousp = r;
|
||||
}
|
||||
|
||||
/* find a free shared memory location to queue ourselves in */
|
||||
static QLp*
|
||||
getqlp(void)
|
||||
{
|
||||
QLp *p, *op;
|
||||
|
||||
op = ql.p;
|
||||
for(p = op+1; ; p++){
|
||||
if(p == &ql.x[nelem(ql.x)])
|
||||
p = ql.x;
|
||||
if(p == op)
|
||||
abort();
|
||||
if(_tas(&(p->inuse)) == 0){
|
||||
ql.p = p;
|
||||
p->next = nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
qlock(QLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(!q->locked){
|
||||
q->locked = 1;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* chain into waiting list */
|
||||
mp = getqlp();
|
||||
p = q->tail;
|
||||
if(p == nil)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->state = Queuing;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
void
|
||||
qunlock(QLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
p = q->head;
|
||||
if(p != nil){
|
||||
/* wakeup head waiting process */
|
||||
q->head = p->next;
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
unlock(&q->lock);
|
||||
while((*_rendezvousp)((ulong)p, 0x12345) == ~0)
|
||||
;
|
||||
return;
|
||||
}
|
||||
q->locked = 0;
|
||||
unlock(&q->lock);
|
||||
}
|
||||
|
||||
int
|
||||
canqlock(QLock *q)
|
||||
{
|
||||
if(!canlock(&q->lock))
|
||||
return 0;
|
||||
if(!q->locked){
|
||||
q->locked = 1;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rlock(RWLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->writer == 0 && q->head == nil){
|
||||
/* no writer, go for it */
|
||||
q->readers++;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
mp = getqlp();
|
||||
p = q->tail;
|
||||
if(p == 0)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->next = nil;
|
||||
mp->state = QueuingR;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait in kernel */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
int
|
||||
canrlock(RWLock *q)
|
||||
{
|
||||
lock(&q->lock);
|
||||
if (q->writer == 0 && q->head == nil) {
|
||||
/* no writer; go for it */
|
||||
q->readers++;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
runlock(RWLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->readers <= 0)
|
||||
abort();
|
||||
p = q->head;
|
||||
if(--(q->readers) > 0 || p == nil){
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* start waiting writer */
|
||||
if(p->state != QueuingW)
|
||||
abort();
|
||||
q->head = p->next;
|
||||
if(q->head == 0)
|
||||
q->tail = 0;
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wakeup waiter */
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
wlock(RWLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->readers == 0 && q->writer == 0){
|
||||
/* noone waiting, go for it */
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait */
|
||||
p = q->tail;
|
||||
mp = getqlp();
|
||||
if(p == nil)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->next = nil;
|
||||
mp->state = QueuingW;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait in kernel */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
int
|
||||
canwlock(RWLock *q)
|
||||
{
|
||||
lock(&q->lock);
|
||||
if (q->readers == 0 && q->writer == 0) {
|
||||
/* no one waiting; go for it */
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
wunlock(RWLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->writer == 0)
|
||||
abort();
|
||||
p = q->head;
|
||||
if(p == nil){
|
||||
q->writer = 0;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
if(p->state == QueuingW){
|
||||
/* start waiting writer */
|
||||
q->head = p->next;
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
unlock(&q->lock);
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
return;
|
||||
}
|
||||
|
||||
if(p->state != QueuingR)
|
||||
abort();
|
||||
|
||||
/* wake waiting readers */
|
||||
while(q->head != nil && q->head->state == QueuingR){
|
||||
p = q->head;
|
||||
q->head = p->next;
|
||||
q->readers++;
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
}
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
q->writer = 0;
|
||||
unlock(&q->lock);
|
||||
}
|
||||
|
||||
void
|
||||
rsleep(Rendez *r)
|
||||
{
|
||||
QLp *t, *me;
|
||||
|
||||
if(!r->l)
|
||||
abort();
|
||||
lock(&r->l->lock);
|
||||
/* we should hold the qlock */
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
|
||||
/* add ourselves to the wait list */
|
||||
me = getqlp();
|
||||
me->state = Sleeping;
|
||||
if(r->head == nil)
|
||||
r->head = me;
|
||||
else
|
||||
r->tail->next = me;
|
||||
me->next = nil;
|
||||
r->tail = me;
|
||||
|
||||
/* pass the qlock to the next guy */
|
||||
t = r->l->head;
|
||||
if(t){
|
||||
r->l->head = t->next;
|
||||
if(r->l->head == nil)
|
||||
r->l->tail = nil;
|
||||
unlock(&r->l->lock);
|
||||
while((*_rendezvousp)((ulong)t, 0x12345) == ~0)
|
||||
;
|
||||
}else{
|
||||
r->l->locked = 0;
|
||||
unlock(&r->l->lock);
|
||||
}
|
||||
|
||||
/* wait for a wakeup */
|
||||
while((*_rendezvousp)((ulong)me, 0x23456) == ~0)
|
||||
;
|
||||
me->inuse = 0;
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
rwakeup(Rendez *r)
|
||||
{
|
||||
QLp *t;
|
||||
|
||||
/*
|
||||
* take off wait and put on front of queue
|
||||
* put on front so guys that have been waiting will not get starved
|
||||
*/
|
||||
|
||||
if(!r->l)
|
||||
abort();
|
||||
lock(&r->l->lock);
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
|
||||
t = r->head;
|
||||
if(t == nil){
|
||||
unlock(&r->l->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->head = t->next;
|
||||
if(r->head == nil)
|
||||
r->tail = nil;
|
||||
|
||||
t->next = r->l->head;
|
||||
r->l->head = t;
|
||||
if(r->l->tail == nil)
|
||||
r->l->tail = t;
|
||||
|
||||
t->state = Queuing;
|
||||
unlock(&r->l->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
rwakeupall(Rendez *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; rwakeup(r); i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
89
src/lib9/rand.c
Normal file
89
src/lib9/rand.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <lib9.h>
|
||||
|
||||
/*
|
||||
* algorithm by
|
||||
* D. P. Mitchell & J. A. Reeds
|
||||
*/
|
||||
|
||||
#define LEN 607
|
||||
#define TAP 273
|
||||
#define MASK 0x7fffffffL
|
||||
#define A 48271
|
||||
#define M 2147483647
|
||||
#define Q 44488
|
||||
#define R 3399
|
||||
#define NORM (1.0/(1.0+MASK))
|
||||
|
||||
static ulong rng_vec[LEN];
|
||||
static ulong* rng_tap = rng_vec;
|
||||
static ulong* rng_feed = 0;
|
||||
static Lock lk;
|
||||
|
||||
static void
|
||||
isrand(long seed)
|
||||
{
|
||||
long lo, hi, x;
|
||||
int i;
|
||||
|
||||
rng_tap = rng_vec;
|
||||
rng_feed = rng_vec+LEN-TAP;
|
||||
seed = seed%M;
|
||||
if(seed < 0)
|
||||
seed += M;
|
||||
if(seed == 0)
|
||||
seed = 89482311;
|
||||
x = seed;
|
||||
/*
|
||||
* Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
|
||||
*/
|
||||
for(i = -20; i < LEN; i++) {
|
||||
hi = x / Q;
|
||||
lo = x % Q;
|
||||
x = A*lo - R*hi;
|
||||
if(x < 0)
|
||||
x += M;
|
||||
if(i >= 0)
|
||||
rng_vec[i] = x;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
srand(long seed)
|
||||
{
|
||||
lock(&lk);
|
||||
isrand(seed);
|
||||
unlock(&lk);
|
||||
}
|
||||
|
||||
long
|
||||
lrand(void)
|
||||
{
|
||||
ulong x;
|
||||
|
||||
lock(&lk);
|
||||
|
||||
rng_tap--;
|
||||
if(rng_tap < rng_vec) {
|
||||
if(rng_feed == 0) {
|
||||
isrand(1);
|
||||
rng_tap--;
|
||||
}
|
||||
rng_tap += LEN;
|
||||
}
|
||||
rng_feed--;
|
||||
if(rng_feed < rng_vec)
|
||||
rng_feed += LEN;
|
||||
x = (*rng_feed + *rng_tap) & MASK;
|
||||
*rng_feed = x;
|
||||
|
||||
unlock(&lk);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
rand(void)
|
||||
{
|
||||
return lrand() & 0x7fff;
|
||||
}
|
||||
|
||||
21
src/lib9/readn.c
Normal file
21
src/lib9/readn.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#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;
|
||||
}
|
||||
180
src/lib9/rendez.c
Normal file
180
src/lib9/rendez.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
NAME
|
||||
rendezvous - user level process synchronization
|
||||
|
||||
SYNOPSIS
|
||||
ulong rendezvous(ulong tag, ulong value)
|
||||
|
||||
DESCRIPTION
|
||||
The rendezvous system call allows two processes to synchro-
|
||||
nize and exchange a value. In conjunction with the shared
|
||||
memory system calls (see segattach(2) and fork(2)), it
|
||||
enables parallel programs to control their scheduling.
|
||||
|
||||
Two processes wishing to synchronize call rendezvous with a
|
||||
common tag, typically an address in memory they share. One
|
||||
process will arrive at the rendezvous first; it suspends
|
||||
execution until a second arrives. When a second process
|
||||
meets the rendezvous the value arguments are exchanged
|
||||
between the processes and returned as the result of the
|
||||
respective rendezvous system calls. Both processes are
|
||||
awakened when the rendezvous succeeds.
|
||||
|
||||
The set of tag values which two processes may use to
|
||||
rendezvous-their tag space-is inherited when a process
|
||||
forks, unless RFREND is set in the argument to rfork; see
|
||||
fork(2).
|
||||
|
||||
If a rendezvous is interrupted the return value is ~0, so
|
||||
that value should not be used in normal communication.
|
||||
|
||||
* This simulates rendezvous with shared memory, pause, and SIGUSR1.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <lib9.h>
|
||||
|
||||
enum
|
||||
{
|
||||
VOUSHASH = 257,
|
||||
};
|
||||
|
||||
typedef struct Vous Vous;
|
||||
struct Vous
|
||||
{
|
||||
Vous *link;
|
||||
Lock lk;
|
||||
int pid;
|
||||
ulong val;
|
||||
ulong tag;
|
||||
};
|
||||
|
||||
static void
|
||||
ign(int x)
|
||||
{
|
||||
USED(x);
|
||||
}
|
||||
|
||||
void /*__attribute__((constructor))*/
|
||||
ignusr1(void)
|
||||
{
|
||||
signal(SIGUSR1, ign);
|
||||
}
|
||||
|
||||
static Vous vouspool[2048];
|
||||
static int nvousused;
|
||||
static Vous *vousfree;
|
||||
static Vous *voushash[VOUSHASH];
|
||||
static Lock vouslock;
|
||||
|
||||
static Vous*
|
||||
getvous(void)
|
||||
{
|
||||
Vous *v;
|
||||
|
||||
if(vousfree){
|
||||
v = vousfree;
|
||||
vousfree = v->link;
|
||||
}else if(nvousused < nelem(vouspool))
|
||||
v = &vouspool[nvousused++];
|
||||
else
|
||||
abort();
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
putvous(Vous *v)
|
||||
{
|
||||
lock(&vouslock);
|
||||
v->link = vousfree;
|
||||
vousfree = v;
|
||||
unlock(&vouslock);
|
||||
}
|
||||
|
||||
static Vous*
|
||||
findvous(ulong tag, ulong val, int pid)
|
||||
{
|
||||
int h;
|
||||
Vous *v, **l;
|
||||
|
||||
lock(&vouslock);
|
||||
h = tag%VOUSHASH;
|
||||
for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
|
||||
if(v->tag == tag){
|
||||
*l = v->link;
|
||||
unlock(&vouslock);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
v = getvous();
|
||||
v->pid = pid;
|
||||
v->link = voushash[h];
|
||||
v->val = val;
|
||||
v->tag = tag;
|
||||
lock(&v->lk);
|
||||
voushash[h] = v;
|
||||
unlock(&vouslock);
|
||||
return v;
|
||||
}
|
||||
|
||||
#define DBG 0
|
||||
ulong
|
||||
rendezvous(ulong tag, ulong val)
|
||||
{
|
||||
int me, vpid;
|
||||
ulong rval;
|
||||
Vous *v;
|
||||
sigset_t mask;
|
||||
|
||||
me = getpid();
|
||||
v = findvous(tag, val, me);
|
||||
if(v->pid == me){
|
||||
if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
|
||||
/*
|
||||
* No rendezvous partner was found; the next guy
|
||||
* through will find v and wake us, so we must go
|
||||
* to sleep.
|
||||
*
|
||||
* To go to sleep:
|
||||
* 1. disable USR1 signals.
|
||||
* 2. unlock v->lk (tells waker okay to signal us).
|
||||
* 3. atomically suspend and enable USR1 signals.
|
||||
*
|
||||
* The call to ignusr1() could be done once at
|
||||
* process creation instead of every time through rendezvous.
|
||||
*/
|
||||
v->val = val;
|
||||
ignusr1();
|
||||
sigprocmask(SIG_SETMASK, NULL, &mask);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
sigdelset(&mask, SIGUSR1);
|
||||
unlock(&v->lk);
|
||||
sigsuspend(&mask);
|
||||
rval = v->val;
|
||||
if(DBG)fprint(2, "pid is %d, awake\n", me);
|
||||
putvous(v);
|
||||
}else{
|
||||
/*
|
||||
* Found someone to meet. Wake him:
|
||||
*
|
||||
* A. lock v->lk (waits for him to get to his step 2)
|
||||
* B. send a USR1
|
||||
*
|
||||
* He won't get the USR1 until he suspends, which
|
||||
* means it must wake him up (it can't get delivered
|
||||
* before he sleeps).
|
||||
*/
|
||||
vpid = v->pid;
|
||||
lock(&v->lk);
|
||||
rval = v->val;
|
||||
v->val = val;
|
||||
unlock(&v->lk);
|
||||
if(kill(vpid, SIGUSR1) < 0){
|
||||
if(DBG)fprint(2, "pid is %d, kill %d failed: %r\n", me, vpid);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
16
src/lib9/strecpy.c
Normal file
16
src/lib9/strecpy.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#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;
|
||||
}
|
||||
20
src/lib9/sysfatal.c
Normal file
20
src/lib9/sysfatal.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <lib9.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);
|
||||
|
||||
fprint(2, "%s; %s\n", argv0 ? argv0 : "<prog>", buf);
|
||||
exits("fatal");
|
||||
}
|
||||
|
||||
6
src/lib9/tas-386.s
Normal file
6
src/lib9/tas-386.s
Normal file
@@ -0,0 +1,6 @@
|
||||
.globl _tas
|
||||
_tas:
|
||||
movl $0xCAFEBABE, %eax
|
||||
movl 4(%esp), %ecx
|
||||
xchgl %eax, 0(%ecx)
|
||||
ret
|
||||
8
src/lib9/test.c
Normal file
8
src/lib9/test.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <lib9.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
werrstr("hello world");
|
||||
print("%r\n");
|
||||
}
|
||||
21
src/lib9/testfork.c
Normal file
21
src/lib9/testfork.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <lib9.h>
|
||||
|
||||
void
|
||||
sayhi(void *v)
|
||||
{
|
||||
USED(v);
|
||||
|
||||
print("hello from subproc\n");
|
||||
print("rendez got %lu from main\n", rendezvous(0x1234, 1234));
|
||||
exits(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
print("hello from main\n");
|
||||
ffork(RFMEM|RFPROC, sayhi, nil);
|
||||
|
||||
print("rendez got %lu from subproc\n", rendezvous(0x1234, 0));
|
||||
exits(0);
|
||||
}
|
||||
106
src/lib9/tokenize.c
Normal file
106
src/lib9/tokenize.c
Normal file
@@ -0,0 +1,106 @@
|
||||
#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;
|
||||
}
|
||||
52
src/lib9/u16.c
Normal file
52
src/lib9/u16.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <lib9.h>
|
||||
static char t16e[] = "0123456789ABCDEF";
|
||||
|
||||
int
|
||||
dec16(uchar *out, int lim, char *in, int n)
|
||||
{
|
||||
int c, w = 0, i = 0;
|
||||
uchar *start = out;
|
||||
uchar *eout = out + lim;
|
||||
|
||||
while(n-- > 0){
|
||||
c = *in++;
|
||||
if('0' <= c && c <= '9')
|
||||
c = c - '0';
|
||||
else if('a' <= c && c <= 'z')
|
||||
c = c - 'a' + 10;
|
||||
else if('A' <= c && c <= 'Z')
|
||||
c = c - 'A' + 10;
|
||||
else
|
||||
continue;
|
||||
w = (w<<4) + c;
|
||||
i++;
|
||||
if(i == 2){
|
||||
if(out + 1 > eout)
|
||||
goto exhausted;
|
||||
*out++ = w;
|
||||
w = 0;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
exhausted:
|
||||
return out - start;
|
||||
}
|
||||
|
||||
int
|
||||
enc16(char *out, int lim, uchar *in, int n)
|
||||
{
|
||||
uint c;
|
||||
char *eout = out + lim;
|
||||
char *start = out;
|
||||
|
||||
while(n-- > 0){
|
||||
c = *in++;
|
||||
if(out + 2 >= eout)
|
||||
goto exhausted;
|
||||
*out++ = t16e[c>>4];
|
||||
*out++ = t16e[c&0xf];
|
||||
}
|
||||
exhausted:
|
||||
*out = 0;
|
||||
return out - start;
|
||||
}
|
||||
109
src/lib9/u32.c
Normal file
109
src/lib9/u32.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <lib9.h>
|
||||
|
||||
int
|
||||
dec32(uchar *dest, int ndest, char *src, int nsrc)
|
||||
{
|
||||
char *s, *tab;
|
||||
uchar *start;
|
||||
int i, u[8];
|
||||
|
||||
if(ndest+1 < (5*nsrc+7)/8)
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=8){
|
||||
for(i=0; i<8; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
|
||||
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
|
||||
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
|
||||
*dest++ = ((0x7 & u[6])<<5) | u[7];
|
||||
src += 8;
|
||||
nsrc -= 8;
|
||||
}
|
||||
if(nsrc > 0){
|
||||
if(nsrc == 1 || nsrc == 3 || nsrc == 6)
|
||||
return -1;
|
||||
for(i=0; i<nsrc; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
if(nsrc == 2)
|
||||
goto out;
|
||||
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
|
||||
if(nsrc == 4)
|
||||
goto out;
|
||||
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
|
||||
if(nsrc == 5)
|
||||
goto out;
|
||||
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
|
||||
}
|
||||
out:
|
||||
return dest-start;
|
||||
}
|
||||
|
||||
int
|
||||
enc32(char *dest, int ndest, uchar *src, int nsrc)
|
||||
{
|
||||
char *tab, *start;
|
||||
int j;
|
||||
|
||||
if(ndest <= (8*nsrc+4)/5 )
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=5){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1c & (src[0]<<2)) | (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[1]>>1));
|
||||
*dest++ = tab[j];
|
||||
j = (0x10 & (src[1]<<4)) | (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1e & (src[2]<<1)) | (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
j = (0x18 & (src[3]<<3)) | (0x07 & (src[4]>>5));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[4]));
|
||||
*dest++ = tab[j];
|
||||
src += 5;
|
||||
nsrc -= 5;
|
||||
}
|
||||
if(nsrc){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1c & (src[0]<<2));
|
||||
if(nsrc == 1)
|
||||
goto out;
|
||||
j |= (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[1]>>1));
|
||||
if(nsrc == 2)
|
||||
goto out;
|
||||
*dest++ = tab[j];
|
||||
j = (0x10 & (src[1]<<4));
|
||||
if(nsrc == 3)
|
||||
goto out;
|
||||
j |= (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1e & (src[2]<<1));
|
||||
if(nsrc == 4)
|
||||
goto out;
|
||||
j |= (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
j = (0x18 & (src[3]<<3));
|
||||
out:
|
||||
*dest++ = tab[j];
|
||||
}
|
||||
*dest = 0;
|
||||
return dest-start;
|
||||
}
|
||||
126
src/lib9/u64.c
Normal file
126
src/lib9/u64.c
Normal file
@@ -0,0 +1,126 @@
|
||||
#include <lib9.h>
|
||||
|
||||
enum {
|
||||
INVAL= 255
|
||||
};
|
||||
|
||||
static uchar t64d[256] = {
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, 62,INVAL,INVAL,INVAL, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
|
||||
};
|
||||
static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
int
|
||||
dec64(uchar *out, int lim, char *in, int n)
|
||||
{
|
||||
ulong b24;
|
||||
uchar *start = out;
|
||||
uchar *e = out + lim;
|
||||
int i, c;
|
||||
|
||||
b24 = 0;
|
||||
i = 0;
|
||||
while(n-- > 0){
|
||||
|
||||
c = t64d[*(uchar*)in++];
|
||||
if(c == INVAL)
|
||||
continue;
|
||||
switch(i){
|
||||
case 0:
|
||||
b24 = c<<18;
|
||||
break;
|
||||
case 1:
|
||||
b24 |= c<<12;
|
||||
break;
|
||||
case 2:
|
||||
b24 |= c<<6;
|
||||
break;
|
||||
case 3:
|
||||
if(out + 3 > e)
|
||||
goto exhausted;
|
||||
|
||||
b24 |= c;
|
||||
*out++ = b24>>16;
|
||||
*out++ = b24>>8;
|
||||
*out++ = b24;
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
switch(i){
|
||||
case 2:
|
||||
if(out + 1 > e)
|
||||
goto exhausted;
|
||||
*out++ = b24>>16;
|
||||
break;
|
||||
case 3:
|
||||
if(out + 2 > e)
|
||||
goto exhausted;
|
||||
*out++ = b24>>16;
|
||||
*out++ = b24>>8;
|
||||
break;
|
||||
}
|
||||
exhausted:
|
||||
return out - start;
|
||||
}
|
||||
|
||||
int
|
||||
enc64(char *out, int lim, uchar *in, int n)
|
||||
{
|
||||
int i;
|
||||
ulong b24;
|
||||
char *start = out;
|
||||
char *e = out + lim;
|
||||
|
||||
for(i = n/3; i > 0; i--){
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in++)<<8;
|
||||
b24 |= *in++;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = t64e[(b24)&0x3f];
|
||||
}
|
||||
|
||||
switch(n%3){
|
||||
case 2:
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in)<<8;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = '=';
|
||||
break;
|
||||
case 1:
|
||||
b24 = (*in)<<16;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = '=';
|
||||
*out++ = '=';
|
||||
break;
|
||||
}
|
||||
exhausted:
|
||||
*out = 0;
|
||||
return out - start;
|
||||
}
|
||||
30
src/lib9/wait.c
Normal file
30
src/lib9/wait.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <lib9.h>
|
||||
|
||||
Waitmsg*
|
||||
wait(void)
|
||||
{
|
||||
int n, l;
|
||||
char buf[512], *fld[5];
|
||||
Waitmsg *w;
|
||||
|
||||
n = await(buf, sizeof buf-1);
|
||||
if(n < 0)
|
||||
return nil;
|
||||
buf[n] = '\0';
|
||||
if(tokenize(buf, fld, nelem(fld)) != nelem(fld)){
|
||||
werrstr("couldn't parse wait message");
|
||||
return nil;
|
||||
}
|
||||
l = strlen(fld[4])+1;
|
||||
w = malloc(sizeof(Waitmsg)+l);
|
||||
if(w == nil)
|
||||
return nil;
|
||||
w->pid = atoi(fld[0]);
|
||||
w->time[0] = atoi(fld[1]);
|
||||
w->time[1] = atoi(fld[2]);
|
||||
w->time[2] = atoi(fld[3]);
|
||||
w->msg = (char*)&w[1];
|
||||
memmove(w->msg, fld[4], l);
|
||||
return w;
|
||||
}
|
||||
|
||||
13
src/lib9/werrstr.c
Normal file
13
src/lib9/werrstr.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <lib9.h>
|
||||
|
||||
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);
|
||||
}
|
||||
258
src/libbio/LICENSE
Normal file
258
src/libbio/LICENSE
Normal file
@@ -0,0 +1,258 @@
|
||||
The Plan 9 software is provided under the terms of the
|
||||
Lucent Public License, Version 1.02, reproduced below,
|
||||
with the following exceptions:
|
||||
|
||||
1. No right is granted to create derivative works of or
|
||||
to redistribute (other than with the Plan 9 Operating System)
|
||||
the screen imprinter fonts identified in subdirectory
|
||||
/lib/font/bit/lucida and printer fonts (Lucida Sans Unicode, Lucida
|
||||
Sans Italic, Lucida Sans Demibold, Lucida Typewriter, Lucida Sans
|
||||
Typewriter83), identified in subdirectory /sys/lib/postscript/font.
|
||||
These directories contain material copyrights by B&H Inc. and Y&Y Inc.
|
||||
|
||||
2. The printer fonts identified in subdirectory /sys/lib/ghostscript/font
|
||||
are subject to the GNU GPL, reproduced in the file /LICENSE.gpl.
|
||||
|
||||
3. The ghostscript program in the subdirectory /sys/src/cmd/gs is
|
||||
covered by the Aladdin Free Public License, reproduced in the file
|
||||
/LICENSE.afpl.
|
||||
|
||||
===================================================================
|
||||
|
||||
Lucent Public License Version 1.02
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
|
||||
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
|
||||
PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
|
||||
Program, and
|
||||
b. in the case of each Contributor,
|
||||
|
||||
i. changes to the Program, and
|
||||
ii. additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program were added to the
|
||||
Program by such Contributor itself or anyone acting on such
|
||||
Contributor's behalf, and the Contributor explicitly consents, in
|
||||
accordance with Section 3C, to characterization of the changes and/or
|
||||
additions as Contributions.
|
||||
|
||||
"Contributor" means LUCENT and any other entity that has Contributed a
|
||||
Contribution to the Program.
|
||||
|
||||
"Distributor" means a Recipient that distributes the Program,
|
||||
modifications to the Program, or any part thereof.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor
|
||||
which are necessarily infringed by the use or sale of its Contribution
|
||||
alone or when combined with the Program.
|
||||
|
||||
"Original Program" means the original version of the software
|
||||
accompanying this Agreement as released by LUCENT, including source
|
||||
code, object code and documentation, if any.
|
||||
|
||||
"Program" means the Original Program and Contributions or any part
|
||||
thereof
|
||||
|
||||
"Recipient" means anyone who receives the Program under this
|
||||
Agreement, including all Contributors.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare derivative works of, publicly display,
|
||||
publicly perform, distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such derivative works, in source code and
|
||||
object code form.
|
||||
|
||||
b. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor, if
|
||||
any, in source code and object code form. The patent license granted
|
||||
by a Contributor shall also apply to the combination of the
|
||||
Contribution of that Contributor and the Program if, at the time the
|
||||
Contribution is added by the Contributor, such addition of the
|
||||
Contribution causes such combination to be covered by the Licensed
|
||||
Patents. The patent license granted by a Contributor shall not apply
|
||||
to (i) any other combinations which include the Contribution, nor to
|
||||
(ii) Contributions of other Contributors. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c. Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity. Each
|
||||
Contributor disclaims any liability to Recipient for claims brought by
|
||||
any other entity based on infringement of intellectual property rights
|
||||
or otherwise. As a condition to exercising the rights and licenses
|
||||
granted hereunder, each Recipient hereby assumes sole responsibility
|
||||
to secure any other intellectual property rights needed, if any. For
|
||||
example, if a third party patent license is required to allow
|
||||
Recipient to distribute the Program, it is Recipient's responsibility
|
||||
to acquire that license before distributing the Program.
|
||||
|
||||
d. Each Contributor represents that to its knowledge it has sufficient
|
||||
copyright rights in its Contribution, if any, to grant the copyright
|
||||
license set forth in this Agreement.
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A. Distributor may choose to distribute the Program in any form under
|
||||
this Agreement or under its own license agreement, provided that:
|
||||
|
||||
a. it complies with the terms and conditions of this Agreement;
|
||||
|
||||
b. if the Program is distributed in source code or other tangible
|
||||
form, a copy of this Agreement or Distributor's own license agreement
|
||||
is included with each copy of the Program; and
|
||||
|
||||
c. if distributed under Distributor's own license agreement, such
|
||||
license agreement:
|
||||
|
||||
i. effectively disclaims on behalf of all Contributors all warranties
|
||||
and conditions, express and implied, including warranties or
|
||||
conditions of title and non-infringement, and implied warranties or
|
||||
conditions of merchantability and fitness for a particular purpose;
|
||||
ii. effectively excludes on behalf of all Contributors all liability
|
||||
for damages, including direct, indirect, special, incidental and
|
||||
consequential damages, such as lost profits; and
|
||||
iii. states that any provisions which differ from this Agreement are
|
||||
offered by that Contributor alone and not by any other party.
|
||||
|
||||
B. Each Distributor must include the following in a conspicuous
|
||||
location in the Program:
|
||||
|
||||
Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
|
||||
Reserved.
|
||||
|
||||
C. In addition, each Contributor must identify itself as the
|
||||
originator of its Contribution in a manner that reasonably allows
|
||||
subsequent Recipients to identify the originator of the Contribution.
|
||||
Also, each Contributor must agree that the additions and/or changes
|
||||
are intended to be a Contribution. Once a Contribution is contributed,
|
||||
it may not thereafter be revoked.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain
|
||||
responsibilities with respect to end users, business partners and the
|
||||
like. While this license is intended to facilitate the commercial use
|
||||
of the Program, the Distributor who includes the Program in a
|
||||
commercial product offering should do so in a manner which does not
|
||||
create potential liability for Contributors. Therefore, if a
|
||||
Distributor includes the Program in a commercial product offering,
|
||||
such Distributor ("Commercial Distributor") hereby agrees to defend
|
||||
and indemnify every Contributor ("Indemnified Contributor") against
|
||||
any losses, damages and costs (collectively"Losses") arising from
|
||||
claims, lawsuits and other legal actions brought by a third party
|
||||
against the Indemnified Contributor to the extent caused by the acts
|
||||
or omissions of such Commercial Distributor in connection with its
|
||||
distribution of the Program in a commercial product offering. The
|
||||
obligations in this section do not apply to any claims or Losses
|
||||
relating to any actual or alleged intellectual property infringement.
|
||||
In order to qualify, an Indemnified Contributor must: a) promptly
|
||||
notify the Commercial Distributor in writing of such claim, and b)
|
||||
allow the Commercial Distributor to control, and cooperate with the
|
||||
Commercial Distributor in, the defense and any related settlement
|
||||
negotiations. The Indemnified Contributor may participate in any such
|
||||
claim at its own expense.
|
||||
|
||||
For example, a Distributor might include the Program in a commercial
|
||||
product offering, Product X. That Distributor is then a Commercial
|
||||
Distributor. If that Commercial Distributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Distributor's responsibility
|
||||
alone. Under this section, the Commercial Distributor would have to
|
||||
defend claims against the Contributors related to those performance
|
||||
claims and warranties, and if a court requires any Contributor to pay
|
||||
any damages as a result, the Commercial Distributor must pay those
|
||||
damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
|
||||
PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and
|
||||
distributing the Program and assumes all risks associated with its
|
||||
exercise of rights under this Agreement, including but not limited to
|
||||
the risks and costs of program errors, compliance with applicable
|
||||
laws, damage to or loss of data, programs or equipment, and
|
||||
unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
|
||||
ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
|
||||
WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
|
||||
DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. EXPORT CONTROL
|
||||
|
||||
Recipient agrees that Recipient alone is responsible for compliance
|
||||
with the United States export administration regulations (and the
|
||||
export control laws and regulation of any other countries).
|
||||
|
||||
8. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against a Contributor with
|
||||
respect to a patent applicable to software (including a cross-claim or
|
||||
counterclaim in a lawsuit), then any patent licenses granted by that
|
||||
Contributor to such Recipient under this Agreement shall terminate as
|
||||
of the date such litigation is filed. In addition, if Recipient
|
||||
institutes patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Program
|
||||
itself (excluding combinations of the Program with other software or
|
||||
hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and
|
||||
survive.
|
||||
|
||||
LUCENT may publish new versions (including revisions) of this
|
||||
Agreement from time to time. Each new version of the Agreement will be
|
||||
given a distinguishing version number. The Program (including
|
||||
Contributions) may always be distributed subject to the version of the
|
||||
Agreement under which it was received. In addition, after a new
|
||||
version of the Agreement is published, Contributor may elect to
|
||||
distribute the Program (including its Contributions) under the new
|
||||
version. No one other than LUCENT has the right to modify this
|
||||
Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
|
||||
Recipient receives no rights or licenses to the intellectual property
|
||||
of any Contributor under this Agreement, whether expressly, by
|
||||
implication, estoppel or otherwise. All rights in the Program not
|
||||
expressly granted under this Agreement are reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and
|
||||
the intellectual property laws of the United States of America. No
|
||||
party to this Agreement will bring a legal action under this Agreement
|
||||
more than one year after the cause of action arose. Each party waives
|
||||
its rights to a jury trial in any resulting litigation.
|
||||
|
||||
7
src/libbio/Make.FreeBSD-386
Normal file
7
src/libbio/Make.FreeBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.HP-UX-9000
Normal file
6
src/libbio/Make.HP-UX-9000
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS=-O -c -Ae -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/libbio/Make.Linux-386
Normal file
7
src/libbio/Make.Linux-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
7
src/libbio/Make.NetBSD-386
Normal file
7
src/libbio/Make.NetBSD-386
Normal file
@@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.OSF1-alpha
Normal file
6
src/libbio/Make.OSF1-alpha
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
2
src/libbio/Make.SunOS-sun4u
Normal file
2
src/libbio/Make.SunOS-sun4u
Normal file
@@ -0,0 +1,2 @@
|
||||
include Make.SunOS-sun4u-$(CC)
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.SunOS-sun4u-cc
Normal file
6
src/libbio/Make.SunOS-sun4u-cc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=cc
|
||||
CFLAGS+=-g -c -I. -O
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
6
src/libbio/Make.SunOS-sun4u-gcc
Normal file
6
src/libbio/Make.SunOS-sun4u-gcc
Normal file
@@ -0,0 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
108
src/libbio/Makefile
Normal file
108
src/libbio/Makefile
Normal file
@@ -0,0 +1,108 @@
|
||||
|
||||
# this works in gnu make
|
||||
SYSNAME:=${shell uname}
|
||||
OBJTYPE:=${shell uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'}
|
||||
|
||||
# this works in bsd make
|
||||
SYSNAME!=uname
|
||||
OBJTYPE!=uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'
|
||||
|
||||
# the gnu rules will mess up bsd but not vice versa,
|
||||
# hence the gnu rules come first.
|
||||
|
||||
include Make.$(SYSNAME)-$(OBJTYPE)
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
NUKEFILES=
|
||||
|
||||
TGZFILES=
|
||||
|
||||
LIB=libbio.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libbio
|
||||
NAME=libbio
|
||||
|
||||
OFILES=\
|
||||
bbuffered.$O\
|
||||
bfildes.$O\
|
||||
bflush.$O\
|
||||
bgetc.$O\
|
||||
bgetd.$O\
|
||||
binit.$O\
|
||||
boffset.$O\
|
||||
bprint.$O\
|
||||
bputc.$O\
|
||||
brdline.$O\
|
||||
brdstr.$O\
|
||||
bread.$O\
|
||||
bseek.$O\
|
||||
bwrite.$O\
|
||||
bgetrune.$O\
|
||||
bputrune.$O\
|
||||
|
||||
HFILES=\
|
||||
bio.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 bio.3 $(PREFIX)/man/man3/bio.3
|
||||
install -m 0644 bio.h $(PREFIX)/include
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
bcat: bcat.$O $(LIB)
|
||||
$(CC) -o bcat bcat.$O $(LIB) -L/usr/local/lib -lfmt -lutf
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
$(AR) $(ARFLAGS) $(LIB) $(OFILES)
|
||||
|
||||
NUKEFILES+=$(LIB)
|
||||
.c.$O:
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
tgz:
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
mkdir $(NAME)-$(VERSION)
|
||||
cp Makefile Make.* README LICENSE NOTICE *.[ch137] rpm.spec bundle.ports $(TGZFILES) $(NAME)-$(VERSION)
|
||||
tar cf - $(NAME)-$(VERSION) | gzip >$(NAME)-$(VERSION).tgz
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES) $(LIB)
|
||||
|
||||
nuke:
|
||||
rm -f $(OFILES) *.tgz *.rpm $(NUKEFILES)
|
||||
|
||||
rpm:
|
||||
make tgz
|
||||
cp $(NAME)-$(VERSION).tgz /usr/src/RPM/SOURCES
|
||||
rpm -ba rpm.spec
|
||||
cp /usr/src/RPM/SRPMS/$(NAME)-$(VERSION)-1.src.rpm .
|
||||
cp /usr/src/RPM/RPMS/i586/$(NAME)-$(VERSION)-1.i586.rpm .
|
||||
scp *.rpm rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
PORTDIR=/usr/ports/$(PORTPLACE)
|
||||
|
||||
ports:
|
||||
make tgz
|
||||
rm -rf $(PORTDIR)
|
||||
mkdir $(PORTDIR)
|
||||
cp $(NAME)-$(VERSION).tgz /usr/ports/distfiles
|
||||
cat bundle.ports | (cd $(PORTDIR) && awk '$$1=="---" && $$3=="---" { ofile=$$2; next} {if(ofile) print >ofile}')
|
||||
(cd $(PORTDIR); make makesum)
|
||||
(cd $(PORTDIR); make)
|
||||
(cd $(PORTDIR); /usr/local/bin/portlint)
|
||||
rm -rf $(PORTDIR)/work
|
||||
shar `find $(PORTDIR)` > ports.shar
|
||||
(cd $(PORTDIR); tar cf - *) | gzip >$(NAME)-$(VERSION)-ports.tgz
|
||||
scp *.tgz rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
.phony: all clean nuke install tgz rpm ports
|
||||
37
src/libbio/Makefile.MID
Normal file
37
src/libbio/Makefile.MID
Normal file
@@ -0,0 +1,37 @@
|
||||
LIB=libbio.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/libbio
|
||||
NAME=libbio
|
||||
|
||||
OFILES=\
|
||||
bbuffered.$O\
|
||||
bfildes.$O\
|
||||
bflush.$O\
|
||||
bgetc.$O\
|
||||
bgetd.$O\
|
||||
binit.$O\
|
||||
boffset.$O\
|
||||
bprint.$O\
|
||||
bputc.$O\
|
||||
brdline.$O\
|
||||
brdstr.$O\
|
||||
bread.$O\
|
||||
bseek.$O\
|
||||
bwrite.$O\
|
||||
bgetrune.$O\
|
||||
bputrune.$O\
|
||||
|
||||
HFILES=\
|
||||
bio.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
install -m 0644 bio.3 $(PREFIX)/man/man3/bio.3
|
||||
install -m 0644 bio.h $(PREFIX)/include
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
bcat: bcat.$O $(LIB)
|
||||
$(CC) -o bcat bcat.$O $(LIB) -L/usr/local/lib -lfmt -lutf
|
||||
|
||||
27
src/libbio/NOTICE
Normal file
27
src/libbio/NOTICE
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
Portions Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved.
|
||||
Portions Copyright © 1997-1999 Vita Nuova Limited. All rights reserved.
|
||||
Portions Copyright © 2000-2002 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
|
||||
|
||||
Under a licence agreement with Lucent Technologies Inc. effective 1st March 2000,
|
||||
Vita Nuova Holdings Limited has the right to determine (within a specified scope)
|
||||
the form and content of sublicences for this software.
|
||||
|
||||
Vita Nuova Holdings Limited now makes this software available as Free
|
||||
Software under the terms of the `GNU General Public LIcense, Version 2'
|
||||
(see the file LICENCE or http://www.fsf.org/copyleft/gpl.html for
|
||||
the full terms and conditions). One of the conditions of that licence
|
||||
is that you must keep intact all notices that refer to that licence and to the absence of
|
||||
of any warranty: for this software, note that includes this NOTICE file in particular.
|
||||
|
||||
This suite of programs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
`GNU General Public License' for more details.
|
||||
|
||||
This copyright NOTICE applies to all files in this directory and
|
||||
subdirectories, unless another copyright notice appears in a given
|
||||
file or subdirectory. If you take code from this software to use in
|
||||
other programs, you must somehow include with it an appropriate
|
||||
copyright notice that includes the copyright notice and the other
|
||||
notices above.
|
||||
7
src/libbio/README
Normal file
7
src/libbio/README
Normal file
@@ -0,0 +1,7 @@
|
||||
This is a Unix port of the Plan 9 buffered I/O library,
|
||||
originally done for the Inferno operating system.
|
||||
|
||||
Russ Cox repackaged this to build as a standalone
|
||||
Unix library. Send comments about packaging to
|
||||
Russ Cox <rsc@post.harvard.edu>
|
||||
|
||||
20
src/libbio/bbuffered.c
Normal file
20
src/libbio/bbuffered.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
42
src/libbio/bcat.c
Normal file
42
src/libbio/bcat.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <fmt.h>
|
||||
#include "bio.h"
|
||||
|
||||
Biobuf bout;
|
||||
|
||||
void
|
||||
bcat(Biobuf *b, char *name)
|
||||
{
|
||||
char buf[1000];
|
||||
int n;
|
||||
|
||||
while((n = Bread(b, buf, sizeof buf)) > 0){
|
||||
if(Bwrite(&bout, buf, n) < 0)
|
||||
fprint(2, "writing during %s: %r\n", name);
|
||||
}
|
||||
if(n < 0)
|
||||
fprint(2, "reading %s: %r\n", name);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
Biobuf b, *bp;
|
||||
|
||||
Binit(&bout, 1, O_WRONLY);
|
||||
|
||||
if(argc == 1){
|
||||
Binit(&b, 0, O_RDONLY);
|
||||
bcat(&b, "<stdin>");
|
||||
}else{
|
||||
for(i=1; i<argc; i++){
|
||||
if((bp = Bopen(argv[i], O_RDONLY)) == 0){
|
||||
fprint(2, "Bopen %s: %r\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
bcat(bp, argv[i]);
|
||||
Bterm(bp);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
9
src/libbio/bfildes.c
Normal file
9
src/libbio/bfildes.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bfildes(Biobuf *bp)
|
||||
{
|
||||
|
||||
return bp->fid;
|
||||
}
|
||||
33
src/libbio/bflush.c
Normal file
33
src/libbio/bflush.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
52
src/libbio/bgetc.c
Normal file
52
src/libbio/bgetc.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "lib9.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) {
|
||||
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;
|
||||
}
|
||||
36
src/libbio/bgetd.c
Normal file
36
src/libbio/bgetd.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
47
src/libbio/bgetrune.c
Normal file
47
src/libbio/bgetrune.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
142
src/libbio/binit.c
Normal file
142
src/libbio/binit.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "lib9.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) {
|
||||
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*
|
||||
Bopen(char *name, int mode)
|
||||
{
|
||||
Biobuf *bp;
|
||||
int f;
|
||||
|
||||
switch(mode) {
|
||||
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 = malloc(sizeof(Biobuf));
|
||||
if(bp == 0)
|
||||
return 0;
|
||||
Binits(bp, f, mode, bp->b, sizeof(bp->b));
|
||||
bp->flag = Bmagic;
|
||||
return bp;
|
||||
}
|
||||
|
||||
int
|
||||
Bterm(Biobuf *bp)
|
||||
{
|
||||
|
||||
deinstall(bp);
|
||||
Bflush(bp);
|
||||
if(bp->flag == Bmagic) {
|
||||
bp->flag = 0;
|
||||
close(bp->fid);
|
||||
free(bp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
336
src/libbio/bio.3
Normal file
336
src/libbio/bio.3
Normal file
@@ -0,0 +1,336 @@
|
||||
.TH BIO 3
|
||||
.SH NAME
|
||||
Bopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetd, Bungetc, Bread, Bseek, Boffset, Bfildes, Blinelen, Bputc, Bprint, Bvprint, Bwrite, Bflush, Bterm, Bbuffered \- buffered input/output
|
||||
.SH SYNOPSIS
|
||||
.ta \w'Biobuf* 'u
|
||||
.B #include <fmt.h>
|
||||
.B #include <bio.h>
|
||||
.PP
|
||||
.B
|
||||
Biobuf* Bopen(char *file, int mode)
|
||||
.PP
|
||||
.B
|
||||
int Binit(Biobuf *bp, int fd, int mode)
|
||||
.PP
|
||||
.B
|
||||
int Bterm(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bprint(Biobuf *bp, char *format, ...)
|
||||
.PP
|
||||
.B
|
||||
int Bvprint(Biobuf *bp, char *format, va_list arglist);
|
||||
.PP
|
||||
.B
|
||||
void* Brdline(Biobuf *bp, int delim)
|
||||
.PP
|
||||
.B
|
||||
char* Brdstr(Biobuf *bp, int delim, int nulldelim)
|
||||
.PP
|
||||
.B
|
||||
int Blinelen(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
off_t Boffset(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bfildes(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bgetc(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
long Bgetrune(Biobufhdr *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bgetd(Biobuf *bp, double *d)
|
||||
.PP
|
||||
.B
|
||||
int Bungetc(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bungetrune(Biobufhdr *bp)
|
||||
.PP
|
||||
.B
|
||||
off_t Bseek(Biobuf *bp, off_t n, int type)
|
||||
.PP
|
||||
.B
|
||||
int Bputc(Biobuf *bp, int c)
|
||||
.PP
|
||||
.B
|
||||
int Bputrune(Biobufhdr *bp, long c)
|
||||
.PP
|
||||
.B
|
||||
long Bread(Biobuf *bp, void *addr, long nbytes)
|
||||
.PP
|
||||
.B
|
||||
long Bwrite(Biobuf *bp, void *addr, long nbytes)
|
||||
.PP
|
||||
.B
|
||||
int Bflush(Biobuf *bp)
|
||||
.PP
|
||||
.B
|
||||
int Bbuffered(Biobuf *bp)
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
These routines implement fast buffered I/O.
|
||||
I/O on different file descriptors is independent.
|
||||
.PP
|
||||
.I Bopen
|
||||
opens
|
||||
.I file
|
||||
for mode
|
||||
.B O_RDONLY
|
||||
or creates for mode
|
||||
.BR O_WRONLY .
|
||||
It calls
|
||||
.IR malloc (3)
|
||||
to allocate a buffer.
|
||||
.PP
|
||||
.I Binit
|
||||
initializes a buffer
|
||||
with the open file descriptor passed in
|
||||
by the user.
|
||||
.PP
|
||||
Arguments
|
||||
of types pointer to Biobuf and pointer to Biobuf
|
||||
can be used interchangeably in the following routines.
|
||||
.PP
|
||||
.IR Bopen ,
|
||||
.IR Binit ,
|
||||
or
|
||||
.I Binits
|
||||
should be called before any of the
|
||||
other routines on that buffer.
|
||||
.I Bfildes
|
||||
returns the integer file descriptor of the associated open file.
|
||||
.PP
|
||||
.I Bterm
|
||||
flushes the buffer for
|
||||
.IR bp .
|
||||
If the buffer was allocated by
|
||||
.IR Bopen ,
|
||||
the buffer is
|
||||
.I freed
|
||||
and the file is closed.
|
||||
.PP
|
||||
.I Brdline
|
||||
reads a string from the file associated with
|
||||
.I bp
|
||||
up to and including the first
|
||||
.I delim
|
||||
character.
|
||||
The delimiter character at the end of the line is
|
||||
not altered.
|
||||
.I Brdline
|
||||
returns a pointer to the start of the line or
|
||||
.L 0
|
||||
on end-of-file or read error.
|
||||
.I Blinelen
|
||||
returns the length (including the delimiter)
|
||||
of the most recent string returned by
|
||||
.IR Brdline .
|
||||
.PP
|
||||
.I Brdstr
|
||||
returns a
|
||||
.IR malloc (3)-allocated
|
||||
buffer containing the next line of input delimited by
|
||||
.IR delim ,
|
||||
terminated by a NUL (0) byte.
|
||||
Unlike
|
||||
.IR Brdline ,
|
||||
which returns when its buffer is full even if no delimiter has been found,
|
||||
.I Brdstr
|
||||
will return an arbitrarily long line in a single call.
|
||||
If
|
||||
.I nulldelim
|
||||
is set, the terminal delimiter will be overwritten with a NUL.
|
||||
After a successful call to
|
||||
.IR Brdstr ,
|
||||
the return value of
|
||||
.I Blinelen
|
||||
will be the length of the returned buffer, excluding the NUL.
|
||||
.PP
|
||||
.I Bgetc
|
||||
returns the next byte from
|
||||
.IR bp ,
|
||||
or a negative value
|
||||
at end of file.
|
||||
.I Bungetc
|
||||
may be called immediately after
|
||||
.I Bgetc
|
||||
to allow the same byte to be reread.
|
||||
.PP
|
||||
.I Bgetrune
|
||||
calls
|
||||
.I Bgetc
|
||||
to read the bytes of the next
|
||||
.SM UTF
|
||||
sequence in the input stream and returns the value of the rune
|
||||
represented by the sequence.
|
||||
It returns a negative value
|
||||
at end of file.
|
||||
.I Bungetrune
|
||||
may be called immediately after
|
||||
.I Bgetrune
|
||||
to allow the same
|
||||
.SM UTF
|
||||
sequence to be reread as either bytes or a rune.
|
||||
.I Bungetc
|
||||
and
|
||||
.I Bungetrune
|
||||
may back up a maximum of five bytes.
|
||||
.PP
|
||||
.I Bgetd
|
||||
uses
|
||||
.I fmtcharstod
|
||||
(undocumented)
|
||||
and
|
||||
.I Bgetc
|
||||
to read the formatted
|
||||
floating-point number in the input stream,
|
||||
skipping initial blanks and tabs.
|
||||
The value is stored in
|
||||
.BR *d.
|
||||
.PP
|
||||
.I Bread
|
||||
reads
|
||||
.I nbytes
|
||||
of data from
|
||||
.I bp
|
||||
into memory starting at
|
||||
.IR addr .
|
||||
The number of bytes read is returned on success
|
||||
and a negative value is returned if a read error occurred.
|
||||
.PP
|
||||
.I Bseek
|
||||
applies
|
||||
.IR lseek (2)
|
||||
to
|
||||
.IR bp .
|
||||
It returns the new file offset.
|
||||
.I Boffset
|
||||
returns the file offset of the next character to be processed.
|
||||
.PP
|
||||
.I Bputc
|
||||
outputs the low order 8 bits of
|
||||
.I c
|
||||
on
|
||||
.IR bp .
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value is returned.
|
||||
Otherwise, a zero is returned.
|
||||
.PP
|
||||
.I Bputrune
|
||||
calls
|
||||
.I Bputc
|
||||
to output the low order
|
||||
16 bits of
|
||||
.I c
|
||||
as a rune
|
||||
in
|
||||
.SM UTF
|
||||
format
|
||||
on the output stream.
|
||||
.PP
|
||||
.I Bprint
|
||||
is a buffered interface to
|
||||
.IR print (2).
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value
|
||||
.RB ( Beof )
|
||||
is returned.
|
||||
Otherwise, the number of bytes output is returned.
|
||||
.I Bvprint
|
||||
does the same except it takes as argument a
|
||||
.B va_list
|
||||
parameter, so it can be called within a variadic function.
|
||||
.PP
|
||||
.I Bwrite
|
||||
outputs
|
||||
.I nbytes
|
||||
of data starting at
|
||||
.I addr
|
||||
to
|
||||
.IR bp .
|
||||
If this causes a
|
||||
.IR write
|
||||
to occur and there is an error,
|
||||
a negative value is returned.
|
||||
Otherwise, the number of bytes written is returned.
|
||||
.PP
|
||||
.I Bflush
|
||||
causes any buffered output associated with
|
||||
.I bp
|
||||
to be written.
|
||||
The return is as for
|
||||
.IR Bputc .
|
||||
.I Bflush
|
||||
is called on
|
||||
exit for every buffer still open
|
||||
for writing.
|
||||
.PP
|
||||
.I Bbuffered
|
||||
returns the number of bytes in the buffer.
|
||||
When reading, this is the number of bytes still available from the last
|
||||
read on the file; when writing, it is the number of bytes ready to be
|
||||
written.
|
||||
.PP
|
||||
This library uses
|
||||
.IR fmt (3)
|
||||
for diagnostic messages about internal errors,
|
||||
as well as for the implementation of
|
||||
.I Bprint
|
||||
and
|
||||
.IR Bvprint .
|
||||
It uses
|
||||
.IR utf (3)
|
||||
for the implementation of
|
||||
.I Bgetrune
|
||||
and
|
||||
.IR Bputrune .
|
||||
.SH SEE ALSO
|
||||
.IR atexit (3).
|
||||
.IR open (2),
|
||||
.IR print (3),
|
||||
.IR utf (7)
|
||||
.SH DIAGNOSTICS
|
||||
.I Bio
|
||||
routines that return integers yield
|
||||
.B Beof
|
||||
if
|
||||
.I bp
|
||||
is not the descriptor of an open file.
|
||||
.I Bopen
|
||||
returns zero if the file cannot be opened in the given mode.
|
||||
.SH HISTORY
|
||||
The
|
||||
.IR bio (3)
|
||||
library originally appeared in Plan 9.
|
||||
This is a port of the Plan 9 bio library.
|
||||
.SH BUGS
|
||||
.I Brdline
|
||||
returns an error on strings longer than the buffer associated
|
||||
with the file
|
||||
and also if the end-of-file is encountered
|
||||
before a delimiter.
|
||||
.I Blinelen
|
||||
will tell how many characters are available
|
||||
in these cases.
|
||||
In the case of a true end-of-file,
|
||||
.I Blinelen
|
||||
will return zero.
|
||||
At the cost of allocating a buffer,
|
||||
.I Brdstr
|
||||
sidesteps these issues.
|
||||
.PP
|
||||
The data returned by
|
||||
.I Brdline
|
||||
may be overwritten by calls to any other
|
||||
.I bio
|
||||
routine on the same
|
||||
.IR bp.
|
||||
79
src/libbio/bio.h
Normal file
79
src/libbio/bio.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef _BIOH_
|
||||
#define _BIOH_ 1
|
||||
|
||||
#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*);
|
||||
int Bfildes(Biobuf*);
|
||||
int Bflush(Biobuf*);
|
||||
int Bgetc(Biobuf*);
|
||||
int Bgetd(Biobuf*, double*);
|
||||
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);
|
||||
void* Brdline(Biobuf*, int);
|
||||
long Bread(Biobuf*, void*, long);
|
||||
off_t Bseek(Biobuf*, off_t, int);
|
||||
int Bterm(Biobuf*);
|
||||
int Bungetc(Biobuf*);
|
||||
long Bwrite(Biobuf*, void*, long);
|
||||
char* Brdstr(Biobuf*, int, int);
|
||||
long Bgetrune(Biobuf*);
|
||||
int Bputrune(Biobuf*, long);
|
||||
|
||||
#endif
|
||||
25
src/libbio/boffset.c
Normal file
25
src/libbio/boffset.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#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;
|
||||
}
|
||||
28
src/libbio/bprint.c
Normal file
28
src/libbio/bprint.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "lib9.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 == 0 || 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;
|
||||
}
|
||||
29
src/libbio/bputc.c
Normal file
29
src/libbio/bputc.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
int
|
||||
Bputc(Biobuf *bp, int c)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
loop:
|
||||
i = bp->ocount;
|
||||
j = i+1;
|
||||
if(i != 0) {
|
||||
bp->ocount = j;
|
||||
bp->ebuf[i] = c;
|
||||
return 0;
|
||||
}
|
||||
if(bp->state != Bwactive)
|
||||
return Beof;
|
||||
j = write(bp->fid, bp->bbuf, bp->bsize);
|
||||
if(j == bp->bsize) {
|
||||
bp->ocount = -bp->bsize;
|
||||
bp->offset += j;
|
||||
goto loop;
|
||||
}
|
||||
fprint(2, "Bputc: write error\n");
|
||||
bp->state = Binactive;
|
||||
bp->ocount = 0;
|
||||
return Beof;
|
||||
}
|
||||
23
src/libbio/bputrune.c
Normal file
23
src/libbio/bputrune.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
94
src/libbio/brdline.c
Normal file
94
src/libbio/brdline.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
112
src/libbio/brdstr.c
Normal file
112
src/libbio/brdstr.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
static char*
|
||||
badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = *np;
|
||||
p = realloc(p, n+ndata+1);
|
||||
if(p){
|
||||
memmove(p+n, data, ndata);
|
||||
n += ndata;
|
||||
if(n>0 && nulldelim && p[n-1]==delim)
|
||||
p[--n] = '\0';
|
||||
else
|
||||
p[n] = '\0';
|
||||
*np = n;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
char*
|
||||
Brdstr(Biobuf *bp, int delim, int nulldelim)
|
||||
{
|
||||
char *ip, *ep, *p;
|
||||
int i, j;
|
||||
|
||||
i = -bp->icount;
|
||||
bp->rdline = 0;
|
||||
if(i == 0) {
|
||||
/*
|
||||
* eof or other error
|
||||
*/
|
||||
if(bp->state != Bractive) {
|
||||
if(bp->state == Bracteof)
|
||||
bp->state = Bractive;
|
||||
bp->gbuf = bp->ebuf;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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->icount += j;
|
||||
return badd(nil, &bp->rdline, ip, j, delim, nulldelim);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
p = nil;
|
||||
for(;;){
|
||||
ip = (char*)bp->bbuf + i;
|
||||
while(i < bp->bsize) {
|
||||
j = read(bp->fid, ip, bp->bsize-i);
|
||||
if(j <= 0 && i == 0)
|
||||
return p;
|
||||
if(j <= 0 && i > 0){
|
||||
/*
|
||||
* end of file but no delim. pretend we got a delim
|
||||
* by making the delim \0 and smashing it with nulldelim.
|
||||
*/
|
||||
j = 1;
|
||||
ep = ip;
|
||||
delim = '\0';
|
||||
nulldelim = 1;
|
||||
*ep = delim; /* there will be room for this */
|
||||
}else{
|
||||
bp->offset += j;
|
||||
ep = memchr(ip, delim, j);
|
||||
}
|
||||
i += 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->icount = j - i;
|
||||
return badd(p, &bp->rdline, ip, j, delim, nulldelim);
|
||||
}
|
||||
ip += j;
|
||||
}
|
||||
|
||||
/*
|
||||
* full buffer without finding; add to user string and continue
|
||||
*/
|
||||
p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0);
|
||||
i = 0;
|
||||
bp->icount = 0;
|
||||
bp->gbuf = bp->ebuf;
|
||||
}
|
||||
return 0; /* never happens */
|
||||
}
|
||||
45
src/libbio/bread.c
Normal file
45
src/libbio/bread.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
56
src/libbio/bseek.c
Normal file
56
src/libbio/bseek.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "lib9.h"
|
||||
#include <bio.h>
|
||||
|
||||
off_t
|
||||
Bseek(Biobuf *bp, off_t offset, int base)
|
||||
{
|
||||
off_t n, d;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
45
src/libbio/bundle.ports
Normal file
45
src/libbio/bundle.ports
Normal file
@@ -0,0 +1,45 @@
|
||||
--- Makefile ---
|
||||
# New ports collection makefile for: libbio
|
||||
# Date Created: 11 Feb 2003
|
||||
# Whom: rsc
|
||||
#
|
||||
# THIS LINE NEEDS REPLACING. IT'S HERE TO GET BY PORTLINT
|
||||
# $FreeBSD: ports/devel/libbio/Makefile,v 1.1 2003/02/12 00:51:22 rsc Exp $
|
||||
|
||||
PORTNAME= libbio
|
||||
PORTVERSION= 2.0
|
||||
CATEGORIES= devel
|
||||
MASTER_SITES= http://pdos.lcs.mit.edu/~rsc/software/
|
||||
EXTRACT_SUFX= .tgz
|
||||
|
||||
MAINTAINER= rsc@post.harvard.edu
|
||||
|
||||
DEPENDS= ${PORTSDIR}/devel/libfmt ${PORTSDIR}/devel/libutf
|
||||
|
||||
MAN3= bio.3
|
||||
USE_REINPLACE= yes
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
post-patch:
|
||||
${REINPLACE_CMD} -e 's,$$(PREFIX),${PREFIX},g' ${WRKSRC}/Makefile
|
||||
|
||||
.include <bsd.port.post.mk>
|
||||
--- pkg-comment ---
|
||||
Simple buffered I/O library from Plan 9
|
||||
--- pkg-descr ---
|
||||
Libbio is a port of Plan 9's formatted I/O library.
|
||||
It provides most of the same functionality as stdio or sfio,
|
||||
but with a simpler interface and smaller footprint.
|
||||
|
||||
WWW: http://pdos.lcs.mit.edu/~rsc/software/#libbio
|
||||
http://plan9.bell-labs.com/magic/man2html/2/bio
|
||||
|
||||
Russ Cox
|
||||
rsc@post.harvard.edu
|
||||
--- pkg-plist ---
|
||||
lib/libbio.a
|
||||
include/bio.h
|
||||
--- /dev/null ---
|
||||
This is just a way to make sure blank lines don't
|
||||
creep into pkg-plist.
|
||||
38
src/libbio/bwrite.c
Normal file
38
src/libbio/bwrite.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "lib9.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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user