Fighting the good fight.

Move libfmt, libutf into subdirectories of lib9.

Add poll-based socket i/o to libthread, so that we can
avoid using multiple procs when possible, thus removing
dependence on crappy pthreads implementations.

Convert samterm, acme to the single-proc libthread.

Bring libcomplete, acme up-to-date w.r.t. Plan 9 distribution.
This commit is contained in:
rsc 2004-02-29 22:10:26 +00:00
parent d51419bf43
commit 5a8e63b2f0
107 changed files with 665 additions and 6637 deletions

View File

@ -76,6 +76,7 @@ int isunix;
Queue *outq;
Queue *inq;
int verbose;
int msize = 8192;
void *gethash(Hash**, uint);
int puthash(Hash**, uint, void*);
@ -94,7 +95,6 @@ void *erealloc(void*, int);
Queue *qalloc(void);
int sendq(Queue*, void*);
void *recvq(Queue*);
void pollthread(void*);
void connthread(void*);
void connoutthread(void*);
void listenthread(void*);
@ -125,7 +125,6 @@ threadmain(int argc, char **argv)
{
char *file;
if(verbose) fprint(2, "9pserve running\n");
ARGBEGIN{
default:
usage();
@ -143,6 +142,7 @@ threadmain(int argc, char **argv)
break;
}ARGEND
if(verbose) fprint(2, "9pserve running\n");
if(argc != 1)
usage();
addr = argv[0];
@ -150,8 +150,19 @@ threadmain(int argc, char **argv)
if((afd = announce(addr, adir)) < 0)
sysfatal("announce %s: %r", addr);
proccreate(mainproc, nil, STACK);
threadexits(0);
if(verbose) fprint(2, "9pserve forking\n");
switch(fork()){
case -1:
sysfatal("fork: %r");
case 0:
if(verbose) fprint(2, "running mainproc\n");
mainproc(nil);
if(verbose) fprint(2, "mainproc finished\n");
_exits(0);
default:
if(verbose) fprint(2, "9pserve exiting\n");
_exits(0);
}
}
void
@ -161,8 +172,6 @@ mainproc(void *v)
Fcall f;
USED(v);
yield(); /* let threadmain exit */
atnotify(ignorepipe, 1);
fmtinstall('D', dirfmt);
fmtinstall('M', dirmodefmt);
@ -174,7 +183,7 @@ mainproc(void *v)
f.type = Tversion;
f.version = "9P2000";
f.msize = 8192;
f.msize = msize;
f.tag = NOTAG;
n = convS2M(&f, vbuf, sizeof vbuf);
if(verbose > 1) fprint(2, "* <- %F\n", &f);
@ -182,12 +191,13 @@ mainproc(void *v)
n = read9pmsg(0, vbuf, sizeof vbuf);
if(convM2S(vbuf, n, &f) != n)
sysfatal("convM2S failure");
if(f.msize < msize)
msize = f.msize;
if(verbose > 1) fprint(2, "* -> %F\n", &f);
threadcreate(inputthread, nil, STACK);
threadcreate(outputthread, nil, STACK);
threadcreate(listenthread, nil, STACK);
threadcreateidle(pollthread, nil, STACK);
threadexits(0);
}
@ -296,8 +306,8 @@ connthread(void *arg)
case Tversion:
m->rx.tag = m->tx.tag;
m->rx.msize = m->tx.msize;
if(m->rx.msize > 8192)
m->rx.msize = 8192;
if(m->rx.msize > msize)
m->rx.msize = msize;
m->rx.version = "9P2000";
m->rx.type = Rversion;
send9pmsg(m);
@ -480,7 +490,7 @@ openfdthread(void *v)
m->internal = 1;
m->c = c;
m->tx.type = Tread;
m->tx.count = 8192;
m->tx.count = msize - IOHDRSZ;
m->tx.fid = fid->fid;
m->tx.tag = m->tag;
m->tx.offset = tot;
@ -506,7 +516,10 @@ openfdthread(void *v)
}else{
for(;;){
if(verbose) fprint(2, "twrite...");
if((n=ioread(io, c->fd, buf, sizeof buf)) <= 0){
n = sizeof buf;
if(n > msize)
n = msize;
if((n=ioread(io, c->fd, buf, n)) <= 0){
if(n < 0)
fprint(2, "pipe read error: %r\n");
m = nil;
@ -1122,106 +1135,23 @@ struct Ioproc
int index;
};
static struct Ioproc **pio;
static struct pollfd *pfd;
static int npfd;
static struct Ioproc *iofree;
Ioproc*
ioproc(void)
{
Ioproc *io;
if(iofree == nil){
pfd = erealloc(pfd, (npfd+1)*sizeof(pfd[0]));
pfd[npfd].events = 0;
pfd[npfd].fd = -1;
iofree = emalloc(sizeof(Ioproc));
iofree->index = npfd;
iofree->c = chancreate(sizeof(ulong), 1);
pio = erealloc(pio, (npfd+1)*sizeof(pio[0]));
pio[npfd] = iofree;
npfd++;
}
io = iofree;
iofree = io->next;
return io;
return (Ioproc*)-1;
}
void
closeioproc(Ioproc *io)
{
io->next = iofree;
iofree = io;
}
void
pollthread(void *v)
{
int i, n;
for(;;){
yield();
for(i=0; i<npfd; i++)
pfd[i].revents = 0;
if(verbose){
fprint(2, "poll:");
for(i=0; i<npfd; i++)
if(pfd[i].events)
fprint(2, " %d%c", pfd[i].fd, pfd[i].events==POLLIN ? 'r' : pfd[i].events==POLLOUT ? 'w' : '?');
fprint(2, "\n");
}
n = poll(pfd, npfd, -1);
if(n <= 0)
continue;
for(i=0; i<npfd; i++)
if(pfd[i].fd != -1 && pfd[i].revents){
pfd[i].fd = -1;
pfd[i].events = 0;
pfd[i].revents = 0;
nbsendul(pio[i]->c, 1);
}
}
}
static void
noblock(int fd)
{
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
}
static void
xwait(Ioproc *io, int fd, int e)
{
if(verbose) fprint(2, "wait for %d%c\n", fd, e==POLLIN ? 'r' : 'w');
pfd[io->index].fd = fd;
pfd[io->index].events = e;
recvul(io->c);
if(verbose) fprint(2, "got %d\n", fd);
}
static void
rwait(Ioproc *io, int fd)
{
xwait(io, fd, POLLIN);
}
static void
wwait(Ioproc *io, int fd)
{
xwait(io, fd, POLLOUT);
}
long
ioread(Ioproc *io, int fd, void *v, long n)
{
long r;
USED(io);
noblock(fd);
while((r=read(fd, v, n)) < 0 && errno == EWOULDBLOCK)
rwait(io, fd);
return r;
return threadread(fd, v, n);
}
long
@ -1247,9 +1177,16 @@ iorecvfd(Ioproc *io, int fd)
{
int r;
noblock(fd);
while((r=recvfd(fd)) < 0 && errno == EWOULDBLOCK)
rwait(io, fd);
threadfdnoblock(fd);
while((r=recvfd(fd)) < 0){
if(errno == EINTR)
continue;
if(errno == EWOULDBLOCK || errno == EAGAIN){
threadfdwait(fd, 'r');
continue;
}
break;
}
return r;
}
@ -1258,23 +1195,24 @@ iosendfd(Ioproc *io, int s, int fd)
{
int r;
noblock(s);
while((r=sendfd(s, fd)) < 0 && errno == EWOULDBLOCK)
wwait(io, s);
if(r < 0) fprint(2, "sent %d, %d\n", s, fd);
threadfdnoblock(s);
while((r=sendfd(s, fd)) < 0){
if(errno == EINTR)
continue;
if(errno == EWOULDBLOCK || errno == EAGAIN){
threadfdwait(fd, 'w');
continue;
}
break;
}
return r;
}
static long
_iowrite(Ioproc *io, int fd, void *v, long n)
{
long r;
USED(io);
noblock(fd);
while((r=write(fd, v, n)) < 0 && errno == EWOULDBLOCK)
wwait(io, fd);
return r;
return threadwrite(fd, v, n);
}
long
@ -1305,9 +1243,16 @@ iolisten(Ioproc *io, char *dir, char *ndir)
if((fd = _p9netfd(dir)) < 0)
return -1;
noblock(fd);
while((r=listen(dir, ndir)) < 0 && errno == EWOULDBLOCK)
rwait(io, fd);
threadfdnoblock(fd);
while((r=listen(dir, ndir)) < 0){
if(errno == EINTR)
continue;
if(errno == EWOULDBLOCK || errno == EAGAIN){
threadfdwait(fd, 'r');
continue;
}
break;
}
return r;
}
@ -1317,9 +1262,16 @@ ioaccept(Ioproc *io, int fd, char *dir)
int r;
USED(io);
noblock(fd);
while((r=accept(fd, dir)) < 0 && errno == EWOULDBLOCK)
rwait(io, fd);
threadfdnoblock(fd);
while((r=accept(fd, dir)) < 0){
if(errno == EINTR)
continue;
if(errno == EWOULDBLOCK || errno == EAGAIN){
threadfdwait(fd, 'r');
continue;
}
break;
}
return r;
}

View File

@ -59,7 +59,6 @@ threadmain(int argc, char *argv[])
{
int i;
char *p, *loadfile;
char buf[256];
Column *c;
int ncol;
Display *d;
@ -70,6 +69,9 @@ threadmain(int argc, char *argv[])
loadfile = nil;
ARGBEGIN{
case 'a':
globalautoindent = TRUE;
break;
case 'b':
bartflag = TRUE;
break;
@ -98,7 +100,7 @@ threadmain(int argc, char *argv[])
break;
default:
Usage:
fprint(2, "usage: acme -c ncol -f fontname -F fixedwidthfontname -l loadfile\n");
fprint(2, "usage: acme -a -c ncol -f fontname -F fixedwidthfontname -l loadfile\n");
exits("usage");
}ARGEND
@ -183,7 +185,7 @@ threadmain(int argc, char *argv[])
fprint(2, "acme: can't initialize plumber: %r\n");
else{
cplumb = chancreate(sizeof(Plumbmsg*), 0);
proccreate(plumbproc, nil, STACK);
threadcreate(plumbproc, nil, STACK);
}
plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
@ -315,7 +317,7 @@ acmeerrorproc(void *v)
USED(v);
threadsetname("acmeerrorproc");
buf = emalloc(8192+1);
while((n=read(errorfd, buf, 8192)) >= 0){
while((n=threadread(errorfd, buf, 8192)) >= 0){
buf[n] = '\0';
sendp(cerr, estrdup(buf));
}
@ -324,8 +326,7 @@ acmeerrorproc(void *v)
void
acmeerrorinit(void)
{
int fd, pfd[2];
char buf[64];
int pfd[2];
if(pipe(pfd) < 0)
error("can't create pipe");
@ -351,7 +352,7 @@ acmeerrorinit(void)
errorfd = pfd[1];
if(errorfd < 0)
error("can't re-open acmeerror file");
proccreate(acmeerrorproc, nil, STACK);
threadcreate(acmeerrorproc, nil, STACK);
}
void
@ -362,7 +363,7 @@ plumbproc(void *v)
USED(v);
threadsetname("plumbproc");
for(;;){
m = plumbrecv(plumbeditfd);
m = threadplumbrecv(plumbeditfd);
if(m == nil)
threadexits(nil);
sendp(cplumb, m);
@ -399,6 +400,7 @@ keyboardthread(void *v)
winlock(t->w, 'K');
wincommit(t->w, t);
winunlock(t->w);
flushwarnings(1);
flushimage(display, 1);
}
alts[KTimer].c = nil;
@ -425,6 +427,7 @@ keyboardthread(void *v)
}
if(nbrecv(keyboardctl->c, &r) > 0)
goto casekeyboard;
flushwarnings(1);
flushimage(display, 1);
break;
}
@ -467,6 +470,7 @@ mousethread(void *v)
draw(screen, screen->r, display->white, nil, ZP);
scrlresize();
rowresize(&row, screen->clipr);
flushwarnings(1);
flushimage(display, 1);
break;
case MPlumb:
@ -477,6 +481,7 @@ mousethread(void *v)
else if(strcmp(act, "showdata")==0)
plumbshow(pm);
}
flushwarnings(1);
flushimage(display, 1);
plumbfree(pm);
break;
@ -562,6 +567,7 @@ mousethread(void *v)
goto Continue;
}
Continue:
flushwarnings(0);
flushimage(display, 1);
qunlock(&row.lk);
break;
@ -916,36 +922,48 @@ iconinit(void)
void
acmeputsnarf(void)
{
int fd, i, n;
int i, n;
Fmt f;
char *s;
if(snarffd<0 || snarfbuf.nc==0)
if(snarfbuf.nc==0)
return;
if(snarfbuf.nc > MAXSNARF)
return;
fd = open("/dev/snarf", OWRITE);
if(fd < 0)
return;
fmtstrinit(&f);
for(i=0; i<snarfbuf.nc; i+=n){
n = snarfbuf.nc-i;
if(n >= NSnarf)
n = NSnarf;
bufread(&snarfbuf, i, snarfrune, n);
if(fprint(fd, "%.*S", n, snarfrune) < 0)
if(fmtprint(&f, "%.*S", n, snarfrune) < 0)
break;
}
close(fd);
s = fmtstrflush(&f);
if(s && s[0])
putsnarf(s);
free(s);
}
void
acmegetsnarf()
acmegetsnarf(void)
{
int nulls;
char *s;
int nb, nr, nulls, len;
Rune *r;
if(snarfbuf.nc > MAXSNARF)
s = getsnarf();
if(s == nil || s[0]==0){
free(s);
return;
if(snarffd < 0)
return;
seek(snarffd, 0, 0);
}
len = strlen(s);
r = runemalloc(len+1);
cvttorunes(s, len, r, &nb, &nr, &nulls);
bufreset(&snarfbuf);
bufload(&snarfbuf, 0, snarffd, &nulls);
bufinsert(&snarfbuf, 0, r, nr);
free(r);
free(s);
}

View File

@ -232,6 +232,7 @@ struct Window
uchar isscratch;
uchar filemenu;
uchar dirty;
uchar autoindent;
int id;
Range addr;
Range limit;
@ -486,6 +487,7 @@ enum /* editing */
Collecting,
};
uint globalincref;
uint seq;
uint maxtab; /* size of a tab, in units of the '0' character */
@ -524,10 +526,11 @@ Image *tagcols[NCOL];
Image *textcols[NCOL];
int plumbsendfd;
int plumbeditfd;
extern char wdir[];
extern char wdir[]; /* must use extern because no dimension given */
int editing;
int erroutfd;
int messagesize; /* negotiated in 9P version setup */
int globalautoindent;
Channel *ckeyboard; /* chan(Rune)[10] */
Channel *cplumb; /* chan(Plumbmsg*) */

View File

@ -596,7 +596,7 @@ runpipe(Text *t, int cmd, Rune *cr, int ncr, int state)
r = skipbl(cr, ncr, &n);
if(n == 0)
editerror("no command specified for >");
editerror("no command specified for %c", cmd);
w = nil;
if(state == Inserting){
w = t->w;
@ -949,12 +949,15 @@ filelooper(Cmd *cp, int XY)
/*
* add a ref to all windows to keep safe windows accessed by X
* that would not otherwise have a ref to hold them up during
* the shenanigans.
* the shenanigans. note this with globalincref so that any
* newly created windows start with an extra reference.
*/
allwindows(alllocker, (void*)1);
globalincref = 1;
for(i=0; i<loopstruct.nw; i++)
cmdexec(&loopstruct.w[i]->body, cp->u.cmd);
allwindows(alllocker, (void*)0);
globalincref = 0;
free(loopstruct.w);
loopstruct.w = nil;

View File

@ -462,7 +462,7 @@ getname(Text *t, Text *argt, Rune *arg, int narg, int isput)
dir.nr = 0;
if(n>0 && arg[0]!='/'){
dir = dirname(t, nil, 0);
if(n==1 && dir.r[0]=='.'){ /* sigh */
if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
free(dir.r);
dir.r = nil;
dir.nr = 0;
@ -606,15 +606,15 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
f->qidpath = d->qid.path;
f->mtime = d->mtime;
if(f->unread)
warningew(w, nil, "%s not written; file already exists\n", name);
warning(nil, "%s not written; file already exists\n", name);
else
warningew(w, nil, "%s modified%s%s since last read\n", name, d->muid[0]?" by ":"", d->muid);
warning(nil, "%s modified%s%s since last read\n", name, d->muid[0]?" by ":"", d->muid);
goto Rescue1;
}
}
fd = create(name, OWRITE, 0666);
if(fd < 0){
warningew(w, nil, "can't create file %s: %r\n", name);
warning(nil, "can't create file %s: %r\n", name);
goto Rescue1;
}
r = fbufalloc();
@ -623,7 +623,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
d = dirfstat(fd);
isapp = (d!=nil && d->length>0 && (d->qid.type&QTAPPEND));
if(isapp){
warningew(w, nil, "%s not written; file is append only\n", name);
warning(nil, "%s not written; file is append only\n", name);
goto Rescue2;
}
@ -634,7 +634,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
bufread(&f->b, q, r, n);
m = snprint(s, BUFSIZE+1, "%.*S", n, r);
if(write(fd, s, m) != m){
warningew(w, nil, "can't write file %s: %r\n", name);
warning(nil, "can't write file %s: %r\n", name);
goto Rescue2;
}
}
@ -701,7 +701,7 @@ put(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
f = w->body.file;
name = getname(&w->body, argt, arg, narg, TRUE);
if(name == nil){
warningew(w, nil, "no file name\n");
warning(nil, "no file name\n");
return;
}
namer = bytetorune(name, &nname);
@ -1163,6 +1163,58 @@ incl(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
}
}
static Rune LON[] = { 'O', 'N', 0 };
static Rune LOFF[] = { 'O', 'F', 'F', 0 };
static Rune Lon[] = { 'o', 'n', 0 };
static int
indentval(Rune *s, int n)
{
if(n < 2)
return -1;
if(runestrncmp(s, LON, n) == 0){
globalautoindent = TRUE;
warning(nil, "Indent ON\n");
return -2;
}
if(runestrncmp(s, LOFF, n) == 0){
globalautoindent = FALSE;
warning(nil, "Indent OFF\n");
return -2;
}
return runestrncmp(s, Lon, n) == 0;
}
void
indent(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
{
Rune *a, *r;
Window *w;
int na, len, autoindent;
USED(_0);
USED(_1);
USED(_2);
if(et==nil || et->w==nil)
return;
w = et->w;
autoindent = -1;
getarg(argt, FALSE, TRUE, &r, &len);
if(r!=nil && len>0)
autoindent = indentval(r, len);
else{
a = findbl(arg, narg, &na);
if(a != arg)
autoindent = indentval(arg, narg-na);
}
if(autoindent >= 0)
w->autoindent = autoindent;
if(autoindent != 2)
warning(nil, "%.*S: Indent %s\n", w->body.file->nname, w->body.file->name,
w->autoindent ? "on" : "off");
}
void
tab(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
{
@ -1375,7 +1427,7 @@ runproc(void *argvp)
av[ac++] = arg;
av[ac] = nil;
c->av = av;
procexec(cpid, sfd, av[0], av);
threadexec(cpid, sfd, av[0], av);
/* libthread uses execvp so no need to do this */
#if 0
e = av[0];
@ -1419,10 +1471,10 @@ Hard:
c->text = news;
}
}
procexecl(cpid, sfd, "rc", "rc", "-c", t, nil);
threadexecl(cpid, sfd, "rc", "rc", "-c", t, nil);
Fail:
/* procexec hasn't happened, so send a zero */
/* threadexec hasn't happened, so send a zero */
close(sfd[0]);
close(sfd[1]);
if(sfd[2] != sfd[1])
@ -1482,7 +1534,7 @@ run(Window *win, char *s, Rune *rdir, int ndir, int newns, char *argaddr, char *
arg[7] = c;
arg[8] = cpid;
arg[9] = (void*)iseditcmd;
proccreate(runproc, arg, STACK);
threadcreate(runproc, arg, STACK);
/* mustn't block here because must be ready to answer mount() call in run() */
arg = emalloc(2*sizeof(void*));
arg[0] = c;

View File

@ -27,7 +27,7 @@ void clearmouse(void);
void allwindows(void(*)(Window*, void*), void*);
uint loadfile(int, uint, int*, int(*)(void*, uint, Rune*, int), void*);
Window* errorwin(Mntdir*, int, Window*);
Window* errorwin(Mntdir*, int);
Runestr cleanrname(Runestr);
void run(Window*, char*, Rune*, int, int, char*, char*, int);
void fsysclose(void);
@ -85,7 +85,8 @@ Window* makenewwindow(Text *t);
int expand(Text*, uint, uint, Expand*);
Rune* skipbl(Rune*, int, int*);
Rune* findbl(Rune*, int, int*);
char* edittext(Window*, int, Rune*, int);
char* edittext(Window*, int, Rune*, int);
void flushwarnings(int);
#define runemalloc(a) (Rune*)emalloc((a)*sizeof(Rune))
#define runerealloc(a, b) (Rune*)erealloc((a), (b)*sizeof(Rune))

View File

@ -111,8 +111,7 @@ void
fsysinit(void)
{
int p[2];
int n, fd;
char buf[256], *u;
char *u;
if(pipe(p) < 0)
error("can't create pipe");
@ -122,7 +121,7 @@ fsysinit(void)
fmtinstall('F', fcallfmt);
if((u = getuser()) != nil)
user = estrdup(u);
proccreate(fsysproc, nil, STACK);
threadcreate(fsysproc, nil, STACK);
}
void
@ -138,7 +137,7 @@ fsysproc(void *v)
x = nil;
for(;;){
buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */
n = read9pmsg(sfd, buf, messagesize);
n = threadread9pmsg(sfd, buf, messagesize);
if(n <= 0){
if(closing)
break;
@ -255,7 +254,11 @@ respond(Xfid *x, Fcall *t, char *err)
x->buf = emalloc(messagesize);
n = convS2M(t, x->buf, messagesize);
if(n <= 0)
{
fprint(2, "convert error (n=%d, msgsize %d): have %F\n", n, messagesize, &x->fcall);
fprint(2, "\tresponse: %F\n", t);
error("convert error in convS2M");
}
if(write(sfd, x->buf, n) != n)
error("write error in respond");
free(x->buf);

View File

@ -320,60 +320,18 @@ isfilec(Rune r)
return FALSE;
}
/* Runestr wrapper for cleanname */
Runestr
cleanrname(Runestr rs)
{
int i, j, found;
Rune *b;
int n;
static Rune Lslashdotdot[] = { '/', '.', '.', 0 };
char *s;
int nb, nulls;
b = rs.r;
n = rs.nr;
/* compress multiple slashes */
for(i=0; i<n-1; i++)
if(b[i]=='/' && b[i+1]=='/'){
runemove(b+i, b+i+1, n-i-1);
--n;
--i;
}
/* eliminate ./ */
for(i=0; i<n-1; i++)
if(b[i]=='.' && b[i+1]=='/' && (i==0 || b[i-1]=='/')){
runemove(b+i, b+i+2, n-i-2);
n -= 2;
--i;
}
/* eliminate trailing . */
if(n>=2 && b[n-2]=='/' && b[n-1]=='.')
--n;
do{
/* compress xx/.. */
found = FALSE;
for(i=1; i<=n-3; i++)
if(runeeq(b+i, 3, Lslashdotdot, 3)){
if(i==n-3 || b[i+3]=='/'){
found = TRUE;
break;
}
}
if(found)
for(j=i-1; j>=0; --j)
if(j==0 || b[j-1]=='/'){
i += 3; /* character beyond .. */
if(i<n && b[i]=='/')
++i;
runemove(b+j, b+i, n-i);
n -= (i-j);
break;
}
}while(found);
if(n == 0){
*b = '.';
n = 1;
}
return (Runestr){b, n};
s = runetobyte(rs.r, rs.nr);
cleanname(s);
cvttorunes(s, strlen(s), rs.r, &nb, &rs.nr, &nulls);
free(s);
return rs;
}
Runestr
@ -407,6 +365,11 @@ includename(Text *t, Rune *r, int n)
Window *w;
char buf[128];
Rune Lsysinclude[] = { '/', 's', 'y', 's', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
Rune Lusrinclude[] = { '/', 'u', 's', 'r', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
Rune Lusrlocalinclude[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l',
'/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
Rune Lusrlocalplan9include[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l',
'/', 'p', 'l', 'a', 'n', '9', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
Runestr file;
int i;
@ -429,6 +392,12 @@ includename(Text *t, Rune *r, int n)
if(file.r == nil)
file = includefile(Lsysinclude, r, n);
if(file.r == nil)
file = includefile(Lusrlocalplan9include, r, n);
if(file.r == nil)
file = includefile(Lusrlocalinclude, r, n);
if(file.r == nil)
file = includefile(Lusrinclude, r, n);
if(file.r==nil && objdir!=nil)
file = includefile(objdir, r, n);
if(file.r == nil)
@ -702,13 +671,16 @@ openfile(Text *t, Expand *e)
t->w->dirty = FALSE;
winsettag(t->w);
textsetselect(&t->w->tag, t->w->tag.file->b.nc, t->w->tag.file->b.nc);
if(ow != nil)
if(ow != nil){
for(i=ow->nincl; --i>=0; ){
n = runestrlen(ow->incl[i]);
rp = runemalloc(n);
runemove(rp, ow->incl[i], n);
winaddincl(w, rp, n);
}
w->autoindent = ow->autoindent;
}else
w->autoindent = globalautoindent;
}
if(e->a1 == e->a0)
eval = FALSE;

View File

@ -1,3 +1,5 @@
# Acme is up-to-date w.r.t. sources as of 29 February 2004
PLAN9=../../..
<$PLAN9/src/mkhdr
@ -36,6 +38,6 @@ UPDATE=\
<$PLAN9/src/mkone
LDFLAGS=$LDFLAGS -lcomplete -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -lfmt -lutf -L$X11/lib -lX11
LDFLAGS=$LDFLAGS -lcomplete -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -L$X11/lib -lX11
edit.$O ecmd.$O elog.$O: edit.h

View File

@ -537,7 +537,7 @@ textfilewidth(Text *t, uint q0, int oneelement)
q = q0;
while(q > 0){
r = textreadc(t, q-1);
if(r<=' ')
if(r <= ' ')
break;
if(oneelement && r=='/')
break;
@ -608,10 +608,11 @@ textcomplete(Text *t)
}
if(!c->advance){
warning(nil, "%.*S%s%.*S*\n",
warning(nil, "%.*S%s%.*S*%s\n",
dir.nr, dir.r,
dir.nr>0 && dir.r[dir.nr-1]!='/' ? "/" : "",
nstr, str);
nstr, str,
c->nmatch ? "" : ": no matches in:");
for(i=0; i<c->nfile; i++)
warning(nil, " %s\n", c->filename[i]);
}
@ -643,25 +644,45 @@ texttype(Text *t, Rune r)
rp = &r;
switch(r){
case Kleft:
if(t->q0 > 0)
if(t->q0 > 0){
textcommit(t, TRUE);
textshow(t, t->q0-1, t->q0-1, TRUE);
}
return;
case Kright:
if(t->q1 < t->file->b.nc)
if(t->q1 < t->file->b.nc){
textcommit(t, TRUE);
textshow(t, t->q1+1, t->q1+1, TRUE);
}
return;
case Kdown:
n = t->fr.maxlines/3;
goto case_Down;
case Kpgdown:
n = t->fr.maxlines/2;
n = 2*t->fr.maxlines/3;
case_Down:
q0 = t->org+frcharofpt(&t->fr, Pt(t->fr.r.min.x, t->fr.r.min.y+n*t->fr.font->height));
textsetorigin(t, q0, FALSE);
return;
case Kup:
n = t->fr.maxlines/3;
goto case_Up;
case Kpgup:
n = t->fr.maxlines/2;
n = 2*t->fr.maxlines/3;
case_Up:
q0 = textbacknl(t, t->org, n);
textsetorigin(t, q0, FALSE);
return;
case Khome:
textshow(t, 0, 0, FALSE);
return;
case Kend:
if(t->w)
wincommit(t->w, t);
else
textcommit(t, TRUE);
textshow(t, t->file->b.nc, t->file->b.nc, FALSE);
return;
}
if(t->what == Body){
seq++;
@ -734,6 +755,21 @@ texttype(Text *t, Rune r)
for(i=0; i<t->file->ntext; i++)
textfill(t->file->text[i]);
return;
case '\n':
if(t->w->autoindent){
/* find beginning of previous line using backspace code */
nnb = textbswidth(t, 0x15); /* ^U case */
rp = runemalloc(nnb + 1);
nr = 0;
rp[nr++] = r;
for(i=0; i<nnb; i++){
r = textreadc(t, t->q0-nnb+i);
if(r != ' ' && r != '\t')
break;
rp[nr++] = r;
}
}
break; /* fall through to normal code */
}
/* otherwise ordinary character; just insert, typically in caches of all texts */
for(i=0; i<t->file->ntext; i++){

View File

@ -50,7 +50,7 @@ timerproc(void *v)
nt = 0;
old = msec();
for(;;){
sleep(1); /* will sleep minimum incr */
threadsleep(1); /* will sleep minimum incr */
new = msec();
dt = new-old;
old = new;
@ -98,7 +98,7 @@ void
timerinit(void)
{
ctimer = chancreate(sizeof(Timer*), 100);
proccreate(timerproc, nil, STACK);
threadcreate(timerproc, nil, STACK);
}
Timer*

View File

@ -62,9 +62,11 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
int i, n;
static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
r = runemalloc(ndir+7);
if(n = ndir) /* assign = */
r = runemalloc(ndir+8);
if(n = ndir){ /* assign = */
runemove(r, dir, ndir);
r[n++] = L'/';
}
runemove(r+n, Lpluserrors, 7);
n += 7;
w = lookfile(r, n);
@ -83,12 +85,13 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
runemove(r, incl[i], n);
winaddincl(w, r, n);
}
w->autoindent = globalautoindent;
return w;
}
/* make new window, if necessary; return with it locked */
Window*
errorwin(Mntdir *md, int owner, Window *e)
errorwin(Mntdir *md, int owner)
{
Window *w;
@ -97,51 +100,100 @@ errorwin(Mntdir *md, int owner, Window *e)
w = errorwin1(nil, 0, nil, 0);
else
w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
if(w != e)
winlock(w, owner);
winlock(w, owner);
if(w->col != nil)
break;
/* window was deleted too fast */
if(w != e)
winunlock(w);
winunlock(w);
}
return w;
}
static void
printwarning(Window *ew, Mntdir *md, Rune *r)
typedef struct Warning Warning;
struct Warning{
Mntdir *md;
Buffer buf;
Warning *next;
};
static Warning *warnings;
static
void
addwarningtext(Mntdir *md, Rune *r, int nr)
{
int nr, q0, owner;
Warning *warn;
for(warn = warnings; warn; warn=warn->next){
if(warn->md == md){
bufinsert(&warn->buf, warn->buf.nc, r, nr);
return;
}
}
warn = emalloc(sizeof(Warning));
warn->next = warnings;
warnings = warn;
bufinsert(&warn->buf, 0, r, nr);
}
void
flushwarnings(int dolock)
{
Warning *warn, *next;
Window *w;
Text *t;
int owner, nr, q0, n;
Rune *r;
if(r == nil)
error("runevsmprint failed");
nr = runestrlen(r);
if(dolock)
qlock(&row.lk);
if(row.ncol == 0){ /* really early error */
rowinit(&row, screen->clipr);
rowadd(&row, nil, -1);
rowadd(&row, nil, -1);
if(row.ncol == 0)
error("initializing columns in warning()");
error("initializing columns in flushwarnings()");
}
w = errorwin(md, 'E', ew);
t = &w->body;
owner = w->owner;
if(owner == 0)
w->owner = 'E';
wincommit(w, t);
q0 = textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
textshow(t, q0, q0+nr, 1);
winsettag(t->w);
textscrdraw(t);
w->owner = owner;
w->dirty = FALSE;
if(ew != w)
for(warn=warnings; warn; warn=next) {
w = errorwin(warn->md, 'E');
t = &w->body;
owner = w->owner;
if(owner == 0)
w->owner = 'E';
wincommit(w, t);
/*
* Most commands don't generate much output. For instance,
* Edit ,>cat goes through /dev/cons and is already in blocks
* because of the i/o system, but a few can. Edit ,p will
* put the entire result into a single hunk. So it's worth doing
* this in blocks (and putting the text in a buffer in the first
* place), to avoid a big memory footprint.
*/
r = fbufalloc();
q0 = t->file->b.nc;
for(n = 0; n < warn->buf.nc; n += nr){
nr = warn->buf.nc - n;
if(nr > RBUFSIZE)
nr = RBUFSIZE;
bufread(&warn->buf, n, r, nr);
textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
}
textshow(t, q0, t->file->b.nc, 1);
free(r);
winsettag(t->w);
textscrdraw(t);
w->owner = owner;
w->dirty = FALSE;
winunlock(w);
free(r);
bufclose(&warn->buf);
next = warn->next;
free(warn);
}
warnings = nil;
if(dolock)
qunlock(&row.lk);
}
void
@ -153,23 +205,9 @@ warning(Mntdir *md, char *s, ...)
va_start(arg, s);
r = runevsmprint(s, arg);
va_end(arg);
printwarning(nil, md, r);
}
/*
* Warningew is like warning but avoids locking the error window
* if it's already locked by checking that ew!=error window.
*/
void
warningew(Window *ew, Mntdir *md, char *s, ...)
{
Rune *r;
va_list arg;
va_start(arg, s);
r = runevsmprint(s, arg);
va_end(arg);
printwarning(ew, md, r);
if(r == nil)
error("runevsmprint failed");
addwarningtext(md, r, runestrlen(r));
}
int

View File

@ -26,6 +26,8 @@ wininit(Window *w, Window *clone, Rectangle r)
w->body.w = w;
w->id = ++winid;
incref(&w->ref);
if(globalincref)
incref(&w->ref);
w->ctlfid = ~0;
w->utflastqid = -1;
r1 = r;
@ -141,7 +143,7 @@ winlock(Window *w, int owner)
int i;
File *f;
fprint(2, "winlock %p %d %lux\n", w, owner, getcallerpc(&w));
//fprint(2, "winlock %p %d %lux\n", w, owner, getcallerpc(&w));
f = w->body.file;
for(i=0; i<f->ntext; i++)
winlock1(f->text[i]->w, owner);
@ -153,7 +155,7 @@ winunlock(Window *w)
int i;
File *f;
fprint(2, "winunlock %p %lux\n", w, getcallerpc(&w));
//fprint(2, "winunlock %p %lux\n", w, getcallerpc(&w));
f = w->body.file;
for(i=0; i<f->ntext; i++){
w = f->text[i]->w;

View File

@ -383,7 +383,7 @@ xfidwrite(Xfid *x)
x->fcall.data[x->fcall.count] = 0;
switch(qid){
case Qcons:
w = errorwin(x->f->mntdir, 'X', nil);
w = errorwin(x->f->mntdir, 'X');
t=&w->body;
goto BodyTag;
@ -543,6 +543,7 @@ xfidwrite(Xfid *x)
}
if(w)
winunlock(w);
flushwarnings(1);
}
void
@ -813,6 +814,7 @@ xfideventwrite(Xfid *x, Window *w)
qunlock(&row.lk);
goto Rescue;
}
flushwarnings(0);
qunlock(&row.lk);
}
@ -1030,6 +1032,7 @@ xfidindexread(Xfid *x)
b[n++] = '\n';
}
}
flushwarnings(0);
qunlock(&row.lk);
off = x->fcall.offset;
cnt = x->fcall.count;

View File

@ -2,7 +2,7 @@ PLAN9=../..
<$PLAN9/src/mkhdr
TARG=`ls *.c | sed 's/\.c//'`
LDFLAGS=$LDFLAGS -lthread -lsec -lfs -lmux -lregexp9 -lbio -l9 -lfmt -lutf
LDFLAGS=$LDFLAGS -lthread -lsec -lfs -lmux -lregexp9 -lbio -l9
<$PLAN9/src/mkmany

View File

@ -99,10 +99,11 @@ extproc(void *argv)
c = arg[0];
fd = (int)arg[1];
threadfdnoblock(fd);
i = 0;
for(;;){
i = 1-i; /* toggle */
n = read(fd, plumbbuf[i].data, sizeof plumbbuf[i].data);
n = threadread(fd, plumbbuf[i].data, sizeof plumbbuf[i].data);
if(n <= 0){
fprint(2, "samterm: extern read error: %r\n");
threadexits("extern"); /* not a fatal error */
@ -165,7 +166,7 @@ extstart(void)
plumbc = chancreate(sizeof(int), 0);
arg[0] = plumbc;
arg[1] = (void*)fd;
proccreate(extproc, arg, STACK);
threadcreate(extproc, arg, STACK);
atexit(removeextern);
}
@ -226,9 +227,10 @@ plumbproc(void *argv)
fdp = arg[1];
i = 0;
threadfdnoblock(*fdp);
for(;;){
i = 1-i; /* toggle */
n = read(*fdp, plumbbuf[i].data, READBUFSIZE);
n = threadread(*fdp, plumbbuf[i].data, READBUFSIZE);
if(n <= 0){
fprint(2, "samterm: plumb read error: %r\n");
threadexits("plumb"); /* not a fatal error */
@ -258,7 +260,7 @@ plumbstart(void)
}
arg[0] =plumbc;
arg[1] = &fd;
proccreate(plumbproc, arg, STACK);
threadcreate(plumbproc, arg, STACK);
return 1;
}
#endif
@ -278,9 +280,10 @@ hostproc(void *arg)
c = arg;
i = 0;
threadfdnoblock(hostfd[0]);
for(;;){
i = 1-i; /* toggle */
n = read(hostfd[0], hostbuf[i].data, sizeof hostbuf[i].data);
n = threadread(hostfd[0], hostbuf[i].data, sizeof hostbuf[i].data);
if(n <= 0){
fprint(2, "samterm: host read error: %r\n");
threadexitsall("host");
@ -295,5 +298,5 @@ void
hoststart(void)
{
hostc = chancreate(sizeof(int), 0);
proccreate(hostproc, hostc, STACK);
threadcreate(hostproc, hostc, STACK);
}

View File

@ -71,8 +71,8 @@ _p9strsig(char *s)
return 0;
}
int
await(char *str, int n)
static int
_await(char *str, int n, int opt)
{
int pid, status, cd;
struct rusage ru;
@ -80,8 +80,8 @@ await(char *str, int n)
ulong u, s;
for(;;){
pid = wait3(&status, 0, &ru);
if(pid < 0)
pid = wait3(&status, opt, &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);
@ -103,3 +103,16 @@ await(char *str, int n)
}
}
}
int
await(char *str, int n)
{
return _await(str, n, 0);
}
int
awaitnohang(char *str, int n)
{
return _await(str, n, WNOHANG);
}

View File

@ -3,7 +3,71 @@ PLAN9=../..
LIB=lib9.a
NUM=\
charstod.$O\
pow10.$O\
# Could add errfmt, but we want to pick it up from lib9 instead.
FMTOFILES=\
dofmt.$O\
errfmt.$O\
fltfmt.$O\
fmt.$O\
fmtfd.$O\
fmtfdflush.$O\
fmtlock.$O\
fmtprint.$O\
fmtquote.$O\
fmtrune.$O\
fmtstr.$O\
fmtvprint.$O\
fprint.$O\
nan64.$O\
print.$O\
runefmtstr.$O\
runeseprint.$O\
runesmprint.$O\
runesnprint.$O\
runesprint.$O\
runevseprint.$O\
runevsmprint.$O\
runevsnprint.$O\
seprint.$O\
smprint.$O\
snprint.$O\
sprint.$O\
strtod.$O\
vfprint.$O\
vseprint.$O\
vsmprint.$O\
vsnprint.$O\
$NUM\
UTFOFILES=\
rune.$O\
runestrcat.$O\
runestrchr.$O\
runestrcmp.$O\
runestrcpy.$O\
runestrdup.$O\
runestrlen.$O\
runestrecpy.$O\
runestrncat.$O\
runestrncmp.$O\
runestrncpy.$O\
runestrrchr.$O\
runestrstr.$O\
runetype.$O\
utfecpy.$O\
utflen.$O\
utfnlen.$O\
utfrrune.$O\
utfrune.$O\
utfutf.$O\
OFILES=\
$FMTOFILES\
$UTFOFILES\
_exits.$O\
_p9dialparse.$O\
_p9dir.$O\
@ -85,3 +149,10 @@ HFILES=\
$PLAN9/include/lib9.h\
<$PLAN9/src/mksyslib
%.$O: fmt/%.c
$CC $CFLAGS -Ifmt fmt/$stem.c
%.$O: utf/%.c
$CC $CFLAGS utf/$stem.c

View File

@ -1,6 +1,6 @@
#include <u.h>
#include <libc.h>
#include "../libfmt/nan.h"
#include "fmt/nan.h"
double
NaN(void)

View File

@ -1,15 +1,15 @@
#include <u.h>
#include <libc.h>
Waitmsg*
wait(void)
static Waitmsg*
_wait(int nohang)
{
int n, l;
char buf[512], *fld[5];
Waitmsg *w;
n = await(buf, sizeof buf-1);
if(n < 0)
n = (nohang ? awaitnohang : await)(buf, sizeof buf-1);
if(n <= 0)
return nil;
buf[n] = '\0';
if(tokenize(buf, fld, nelem(fld)) != nelem(fld)){
@ -29,3 +29,15 @@ wait(void)
return w;
}
Waitmsg*
wait(void)
{
return _wait(0);
}
Waitmsg*
waitnohang(void)
{
return _wait(1);
}

View File

@ -41,7 +41,7 @@ strpcmp(const void *va, const void *vb)
Completion*
complete(char *dir, char *s)
{
long i, l, n, nmatch, len, nbytes;
long i, l, n, nfile, len, nbytes;
int fd, minlen;
Dir *dirp;
char **name, *p;
@ -58,8 +58,10 @@ complete(char *dir, char *s)
return nil;
n = dirreadall(fd, &dirp);
if(n <= 0)
if(n <= 0){
close(fd);
return nil;
}
/* find longest string, for allocation */
len = 0;
@ -78,49 +80,51 @@ complete(char *dir, char *s)
/* find the matches */
len = strlen(s);
nmatch = 0;
nfile = 0;
minlen = 1000000;
for(i=0; i<n; i++)
if(strncmp(s, dirp[i].name, len) == 0){
name[nmatch] = dirp[i].name;
mode[nmatch] = dirp[i].mode;
name[nfile] = dirp[i].name;
mode[nfile] = dirp[i].mode;
if(minlen > strlen(dirp[i].name))
minlen = strlen(dirp[i].name);
nmatch++;
nfile++;
}
if(nmatch > 0) {
if(nfile > 0) {
/* report interesting results */
/* trim length back to longest common initial string */
for(i=1; i<nmatch; i++)
for(i=1; i<nfile; i++)
minlen = longestprefixlength(name[0], name[i], minlen);
/* build the answer */
c->complete = (nmatch == 1);
c->complete = (nfile == 1);
c->advance = c->complete || (minlen > len);
c->string = (char*)(c+1);
memmove(c->string, name[0]+len, minlen-len);
if(c->complete)
c->string[minlen++ - len] = (mode[0]&DMDIR)? '/' : ' ';
c->string[minlen - len] = '\0';
c->nmatch = nfile;
} else {
/* no match, so return all possible strings */
for(i=0; i<n; i++){
name[i] = dirp[i].name;
mode[i] = dirp[i].mode;
}
nmatch = n;
nfile = n;
c->nmatch = 0;
}
/* attach list of names */
nbytes = nmatch * sizeof(char*);
for(i=0; i<nmatch; i++)
nbytes = nfile * sizeof(char*);
for(i=0; i<nfile; i++)
nbytes += strlen(name[i]) + 1 + 1;
c->filename = malloc(nbytes);
if(c->filename == nil)
goto Return;
p = (char*)(c->filename + nmatch);
for(i=0; i<nmatch; i++){
p = (char*)(c->filename + nfile);
for(i=0; i<nfile; i++){
c->filename[i] = p;
strcpy(p, name[i]);
p += strlen(p);
@ -128,12 +132,13 @@ complete(char *dir, char *s)
*p++ = '/';
*p++ = '\0';
}
c->nfile = nmatch;
c->nfile = nfile;
qsort(c->filename, c->nfile, sizeof(c->filename[0]), strpcmp);
Return:
free(name);
free(mode);
free(dirp);
close(fd);
return c;
}

View File

@ -454,7 +454,7 @@ _xselect(XEvent *e, XDisplay *xd)
memset(&r, 0, sizeof r);
xe = (XSelectionRequestEvent*)e;
if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d\n",
if(1) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d\n",
xe->target, xe->requestor, xe->property, xe->selection);
r.xselection.property = xe->property;
if(xe->target == _x.targets){

View File

@ -34,6 +34,7 @@ void
_ioproc(void *arg)
{
int i;
int fd;
Keyboardctl *kc;
Rune r;
XEvent xevent;
@ -41,9 +42,11 @@ _ioproc(void *arg)
kc = arg;
threadsetname("kbdproc");
kc->pid = getpid();
fd = XConnectionNumber(_x.kbdcon);
XSelectInput(_x.kbdcon, _x.drawable, KeyPressMask);
for(;;){
XWindowEvent(_x.kbdcon, _x.drawable, KeyPressMask, &xevent);
while(XCheckWindowEvent(_x.kbdcon, _x.drawable, KeyPressMask, &xevent) == False)
threadfdwait(fd, 'r');
switch(xevent.type){
case KeyPress:
i = _xtoplan9kbd(&xevent);
@ -65,11 +68,12 @@ initkeyboard(char *file)
{
Keyboardctl *kc;
threadfdwaitsetup();
kc = mallocz(sizeof(Keyboardctl), 1);
if(kc == nil)
return nil;
kc->c = chancreate(sizeof(Rune), 20);
proccreate(_ioproc, kc, 4096);
threadcreate(_ioproc, kc, 4096);
return kc;
}

View File

@ -47,7 +47,7 @@ static
void
_ioproc(void *arg)
{
int one;
int fd, one;
ulong mask;
Mouse m;
Mousectl *mc;
@ -60,7 +60,10 @@ _ioproc(void *arg)
mc->pid = getpid();
mask = MouseMask|ExposureMask|StructureNotifyMask;
XSelectInput(_x.mousecon, _x.drawable, mask);
fd = XConnectionNumber(_x.mousecon);
for(;;){
while(XPending(_x.mousecon) == False)
threadfdwait(fd, 'r');
XNextEvent(_x.mousecon, &xevent);
switch(xevent.type){
case Expose:
@ -105,12 +108,13 @@ initmouse(char *file, Image *i)
{
Mousectl *mc;
threadfdwaitsetup();
mc = mallocz(sizeof(Mousectl), 1);
if(i)
mc->display = i->display;
mc->c = chancreate(sizeof(Mouse), 0);
mc->resizec = chancreate(sizeof(int), 2);
proccreate(_ioproc, mc, 16384);
threadcreate(_ioproc, mc, 16384);
return mc;
}

View File

@ -1,19 +0,0 @@
/*
* 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.
*/
This is a Unix port of the Plan 9 formatted I/O package.
Please send comments about the packaging
to Russ Cox <rsc@post.harvard.edu>.

View File

@ -1,19 +0,0 @@
/*
* 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.
*/
This is a Unix port of the Plan 9 formatted I/O package.
Please send comments about the packaging
to Russ Cox <rsc@post.harvard.edu>.

View File

@ -1,19 +0,0 @@
/*
* 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.
*/
This is a Unix port of the Plan 9 formatted I/O package.
Please send comments about the packaging
to Russ Cox <rsc@post.harvard.edu>.

View File

@ -1,85 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/*
* Reads a floating-point number by interpreting successive characters
* returned by (*f)(vp). The last call it makes to f terminates the
* scan, so is not a character in the number. It may therefore be
* necessary to back up the input stream up one byte after calling charstod.
*/
double
fmtcharstod(int(*f)(void*), void *vp)
{
double num, dem;
int neg, eneg, dig, exp, c;
num = 0;
neg = 0;
dig = 0;
exp = 0;
eneg = 0;
c = (*f)(vp);
while(c == ' ' || c == '\t')
c = (*f)(vp);
if(c == '-' || c == '+'){
if(c == '-')
neg = 1;
c = (*f)(vp);
}
while(c >= '0' && c <= '9'){
num = num*10 + c-'0';
c = (*f)(vp);
}
if(c == '.')
c = (*f)(vp);
while(c >= '0' && c <= '9'){
num = num*10 + c-'0';
dig++;
c = (*f)(vp);
}
if(c == 'e' || c == 'E'){
c = (*f)(vp);
if(c == '-' || c == '+'){
if(c == '-'){
dig = -dig;
eneg = 1;
}
c = (*f)(vp);
}
while(c >= '0' && c <= '9'){
exp = exp*10 + c-'0';
c = (*f)(vp);
}
}
exp -= dig;
if(exp < 0){
exp = -exp;
eneg = !eneg;
}
dem = __fmtpow10(exp);
if(eneg)
num /= dem;
else
num *= dem;
if(neg)
return -num;
return num;
}

View File

@ -1,558 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/* format the output into f->to and return the number of characters fmted */
int
dofmt(Fmt *f, char *fmt)
{
Rune rune, *rt, *rs;
int r;
char *t, *s;
int n, nfmt;
nfmt = f->nfmt;
for(;;){
if(f->runes){
rt = (Rune*)f->to;
rs = (Rune*)f->stop;
while((r = *(uchar*)fmt) && r != '%'){
if(r < Runeself)
fmt++;
else{
fmt += chartorune(&rune, fmt);
r = rune;
}
FMTRCHAR(f, rt, rs, r);
}
fmt++;
f->nfmt += rt - (Rune *)f->to;
f->to = rt;
if(!r)
return f->nfmt - nfmt;
f->stop = rs;
}else{
t = (char*)f->to;
s = (char*)f->stop;
while((r = *(uchar*)fmt) && r != '%'){
if(r < Runeself){
FMTCHAR(f, t, s, r);
fmt++;
}else{
n = chartorune(&rune, fmt);
if(t + n > s){
t = (char*)__fmtflush(f, t, n);
if(t != nil)
s = (char*)f->stop;
else
return -1;
}
while(n--)
*t++ = *fmt++;
}
}
fmt++;
f->nfmt += t - (char *)f->to;
f->to = t;
if(!r)
return f->nfmt - nfmt;
f->stop = s;
}
fmt = (char*)__fmtdispatch(f, fmt, 0);
if(fmt == nil)
return -1;
}
return 0; /* not reached */
}
void *
__fmtflush(Fmt *f, void *t, int len)
{
if(f->runes)
f->nfmt += (Rune*)t - (Rune*)f->to;
else
f->nfmt += (char*)t - (char *)f->to;
f->to = t;
if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
f->stop = f->to;
return nil;
}
return f->to;
}
/*
* put a formatted block of memory sz bytes long of n runes into the output buffer,
* left/right justified in a field of at least f->width charactes
*/
int
__fmtpad(Fmt *f, int n)
{
char *t, *s;
int i;
t = (char*)f->to;
s = (char*)f->stop;
for(i = 0; i < n; i++)
FMTCHAR(f, t, s, ' ');
f->nfmt += t - (char *)f->to;
f->to = t;
return 0;
}
int
__rfmtpad(Fmt *f, int n)
{
Rune *t, *s;
int i;
t = (Rune*)f->to;
s = (Rune*)f->stop;
for(i = 0; i < n; i++)
FMTRCHAR(f, t, s, ' ');
f->nfmt += t - (Rune *)f->to;
f->to = t;
return 0;
}
int
__fmtcpy(Fmt *f, const void *vm, int n, int sz)
{
Rune *rt, *rs, r;
char *t, *s, *m, *me;
ulong fl;
int nc, w;
m = (char*)vm;
me = m + sz;
w = f->width;
fl = f->flags;
if((fl & FmtPrec) && n > f->prec)
n = f->prec;
if(f->runes){
if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
return -1;
rt = (Rune*)f->to;
rs = (Rune*)f->stop;
for(nc = n; nc > 0; nc--){
r = *(uchar*)m;
if(r < Runeself)
m++;
else if((me - m) >= UTFmax || fullrune(m, me-m))
m += chartorune(&r, m);
else
break;
FMTRCHAR(f, rt, rs, r);
}
f->nfmt += rt - (Rune *)f->to;
f->to = rt;
if(m < me)
return -1;
if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
return -1;
}else{
if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
return -1;
t = (char*)f->to;
s = (char*)f->stop;
for(nc = n; nc > 0; nc--){
r = *(uchar*)m;
if(r < Runeself)
m++;
else if((me - m) >= UTFmax || fullrune(m, me-m))
m += chartorune(&r, m);
else
break;
FMTRUNE(f, t, s, r);
}
f->nfmt += t - (char *)f->to;
f->to = t;
if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
return -1;
}
return 0;
}
int
__fmtrcpy(Fmt *f, const void *vm, int n)
{
Rune r, *m, *me, *rt, *rs;
char *t, *s;
ulong fl;
int w;
m = (Rune*)vm;
w = f->width;
fl = f->flags;
if((fl & FmtPrec) && n > f->prec)
n = f->prec;
if(f->runes){
if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
return -1;
rt = (Rune*)f->to;
rs = (Rune*)f->stop;
for(me = m + n; m < me; m++)
FMTRCHAR(f, rt, rs, *m);
f->nfmt += rt - (Rune *)f->to;
f->to = rt;
if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
return -1;
}else{
if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
return -1;
t = (char*)f->to;
s = (char*)f->stop;
for(me = m + n; m < me; m++){
r = *m;
FMTRUNE(f, t, s, r);
}
f->nfmt += t - (char *)f->to;
f->to = t;
if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
return -1;
}
return 0;
}
/* fmt out one character */
int
__charfmt(Fmt *f)
{
char x[1];
x[0] = va_arg(f->args, int);
f->prec = 1;
return __fmtcpy(f, (const char*)x, 1, 1);
}
/* fmt out one rune */
int
__runefmt(Fmt *f)
{
Rune x[1];
x[0] = va_arg(f->args, int);
return __fmtrcpy(f, (const void*)x, 1);
}
/* public helper routine: fmt out a null terminated string already in hand */
int
fmtstrcpy(Fmt *f, char *s)
{
int p, i;
if(!s)
return __fmtcpy(f, "<nil>", 5, 5);
/* if precision is specified, make sure we don't wander off the end */
if(f->flags & FmtPrec){
p = f->prec;
for(i = 0; i < p; i++)
if(s[i] == 0)
break;
return __fmtcpy(f, s, utfnlen(s, i), i); /* BUG?: won't print a partial rune at end */
}
return __fmtcpy(f, s, utflen(s), strlen(s));
}
/* fmt out a null terminated utf string */
int
__strfmt(Fmt *f)
{
char *s;
s = va_arg(f->args, char *);
return fmtstrcpy(f, s);
}
/* public helper routine: fmt out a null terminated rune string already in hand */
int
fmtrunestrcpy(Fmt *f, Rune *s)
{
Rune *e;
int n, p;
if(!s)
return __fmtcpy(f, "<nil>", 5, 5);
/* if precision is specified, make sure we don't wander off the end */
if(f->flags & FmtPrec){
p = f->prec;
for(n = 0; n < p; n++)
if(s[n] == 0)
break;
}else{
for(e = s; *e; e++)
;
n = e - s;
}
return __fmtrcpy(f, s, n);
}
/* fmt out a null terminated rune string */
int
__runesfmt(Fmt *f)
{
Rune *s;
s = va_arg(f->args, Rune *);
return fmtrunestrcpy(f, s);
}
/* fmt a % */
int
__percentfmt(Fmt *f)
{
Rune x[1];
x[0] = f->r;
f->prec = 1;
return __fmtrcpy(f, (const void*)x, 1);
}
/* fmt an integer */
int
__ifmt(Fmt *f)
{
char buf[70], *p, *conv;
uvlong vu;
ulong u;
int neg, base, i, n, fl, w, isv;
neg = 0;
fl = f->flags;
isv = 0;
vu = 0;
u = 0;
/*
* Unsigned verbs
*/
switch(f->r){
case 'o':
case 'u':
case 'x':
case 'X':
fl |= FmtUnsigned;
break;
}
if(f->r == 'p'){
u = (ulong)va_arg(f->args, void*);
f->r = 'x';
fl |= FmtUnsigned;
}else if(fl & FmtVLong){
isv = 1;
if(fl & FmtUnsigned)
vu = va_arg(f->args, uvlong);
else
vu = va_arg(f->args, vlong);
}else if(fl & FmtLong){
if(fl & FmtUnsigned)
u = va_arg(f->args, ulong);
else
u = va_arg(f->args, long);
}else if(fl & FmtByte){
if(fl & FmtUnsigned)
u = (uchar)va_arg(f->args, int);
else
u = (char)va_arg(f->args, int);
}else if(fl & FmtShort){
if(fl & FmtUnsigned)
u = (ushort)va_arg(f->args, int);
else
u = (short)va_arg(f->args, int);
}else{
if(fl & FmtUnsigned)
u = va_arg(f->args, uint);
else
u = va_arg(f->args, int);
}
conv = "0123456789abcdef";
switch(f->r){
case 'd':
case 'i':
base = 10;
break;
case 'u':
base = 10;
break;
case 'x':
base = 16;
break;
case 'X':
base = 16;
conv = "0123456789ABCDEF";
break;
case 'b':
base = 2;
break;
case 'o':
base = 8;
break;
default:
return -1;
}
if(!(fl & FmtUnsigned)){
if(isv && (vlong)vu < 0){
vu = -(vlong)vu;
neg = 1;
}else if(!isv && (long)u < 0){
u = -(long)u;
neg = 1;
}
}else{
fl &= ~(FmtSign|FmtSpace); /* no + for unsigned conversions */
}
p = buf + sizeof buf - 1;
n = 0;
if(isv){
while(vu){
i = vu % base;
vu /= base;
if((fl & FmtComma) && n % 4 == 3){
*p-- = ',';
n++;
}
*p-- = conv[i];
n++;
}
}else{
while(u){
i = u % base;
u /= base;
if((fl & FmtComma) && n % 4 == 3){
*p-- = ',';
n++;
}
*p-- = conv[i];
n++;
}
}
if(n == 0){
if(!(fl & FmtPrec) || f->prec != 0){
*p-- = '0';
n = 1;
}
fl &= ~FmtSharp;
}
for(w = f->prec; n < w && p > buf+3; n++)
*p-- = '0';
if(neg || (fl & (FmtSign|FmtSpace)))
n++;
if(fl & FmtSharp){
if(base == 16)
n += 2;
else if(base == 8){
if(p[1] == '0')
fl &= ~FmtSharp;
else
n++;
}
}
if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
for(w = f->width; n < w && p > buf+3; n++)
*p-- = '0';
f->width = 0;
}
if(fl & FmtSharp){
if(base == 16)
*p-- = f->r;
if(base == 16 || base == 8)
*p-- = '0';
}
if(neg)
*p-- = '-';
else if(fl & FmtSign)
*p-- = '+';
else if(fl & FmtSpace)
*p-- = ' ';
f->flags &= ~FmtPrec;
return __fmtcpy(f, p + 1, n, n);
}
int
__countfmt(Fmt *f)
{
void *p;
ulong fl;
fl = f->flags;
p = va_arg(f->args, void*);
if(fl & FmtVLong){
*(vlong*)p = f->nfmt;
}else if(fl & FmtLong){
*(long*)p = f->nfmt;
}else if(fl & FmtByte){
*(char*)p = f->nfmt;
}else if(fl & FmtShort){
*(short*)p = f->nfmt;
}else{
*(int*)p = f->nfmt;
}
return 0;
}
int
__flagfmt(Fmt *f)
{
switch(f->r){
case ',':
f->flags |= FmtComma;
break;
case '-':
f->flags |= FmtLeft;
break;
case '+':
f->flags |= FmtSign;
break;
case '#':
f->flags |= FmtSharp;
break;
case ' ':
f->flags |= FmtSpace;
break;
case 'u':
f->flags |= FmtUnsigned;
break;
case 'h':
if(f->flags & FmtShort)
f->flags |= FmtByte;
f->flags |= FmtShort;
break;
case 'L':
f->flags |= FmtLDouble;
break;
case 'l':
if(f->flags & FmtLong)
f->flags |= FmtVLong;
f->flags |= FmtLong;
break;
}
return 1;
}
/* default error format */
int
__badfmt(Fmt *f)
{
char x[3];
x[0] = '%';
x[1] = f->r;
x[2] = '%';
f->prec = 3;
__fmtcpy(f, (const void*)x, 3, 3);
return 0;
}

View File

@ -1,61 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/* format the output into f->to and return the number of characters fmted */
int
dorfmt(Fmt *f, const Rune *fmt)
{
Rune *rt, *rs;
int r;
char *t, *s;
int nfmt;
nfmt = f->nfmt;
for(;;){
if(f->runes){
rt = f->to;
rs = f->stop;
while((r = *fmt++) && r != '%'){
FMTRCHAR(f, rt, rs, r);
}
f->nfmt += rt - (Rune *)f->to;
f->to = rt;
if(!r)
return f->nfmt - nfmt;
f->stop = rs;
}else{
t = f->to;
s = f->stop;
while((r = *fmt++) && r != '%'){
FMTRUNE(f, t, f->stop, r);
}
f->nfmt += t - (char *)f->to;
f->to = t;
if(!r)
return f->nfmt - nfmt;
f->stop = s;
}
fmt = __fmtdispatch(f, fmt, 1);
if(fmt == nil)
return -1;
}
return 0; /* not reached */
}

View File

@ -1,28 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
int
__errfmt(Fmt *f)
{
char *s;
s = strerror(errno);
return fmtstrcpy(f, s);
}

View File

@ -1,610 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include "fmt.h"
#include "fmtdef.h"
#include "nan.h"
enum
{
FDEFLT = 6,
NSIGNIF = 17
};
/*
* first few powers of 10, enough for about 1/2 of the
* total space for doubles.
*/
static double pows10[] =
{
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
};
static double
pow10(int n)
{
double d;
int neg;
neg = 0;
if(n < 0){
if(n < DBL_MIN_10_EXP){
return 0.;
}
neg = 1;
n = -n;
}else if(n > DBL_MAX_10_EXP){
return HUGE_VAL;
}
if(n < (int)(sizeof(pows10)/sizeof(pows10[0])))
d = pows10[n];
else{
d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
for(;;){
n -= sizeof(pows10)/sizeof(pows10[0]) - 1;
if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){
d *= pows10[n];
break;
}
d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
}
}
if(neg){
return 1./d;
}
return d;
}
static int
xadd(char *a, int n, int v)
{
char *b;
int c;
if(n < 0 || n >= NSIGNIF)
return 0;
for(b = a+n; b >= a; b--) {
c = *b + v;
if(c <= '9') {
*b = c;
return 0;
}
*b = '0';
v = 1;
}
*a = '1'; /* overflow adding */
return 1;
}
static int
xsub(char *a, int n, int v)
{
char *b;
int c;
for(b = a+n; b >= a; b--) {
c = *b - v;
if(c >= '0') {
*b = c;
return 0;
}
*b = '9';
v = 1;
}
*a = '9'; /* underflow subtracting */
return 1;
}
static void
xaddexp(char *p, int e)
{
char se[9];
int i;
*p++ = 'e';
if(e < 0) {
*p++ = '-';
e = -e;
}
i = 0;
while(e) {
se[i++] = e % 10 + '0';
e /= 10;
}
if(i == 0) {
*p++ = '0';
} else {
while(i > 0)
*p++ = se[--i];
}
*p++ = '\0';
}
static char*
xdodtoa(char *s1, double f, int chr, int prec, int *decpt, int *rsign)
{
char s2[NSIGNIF+10];
double g, h;
int e, d, i;
int c2, sign, oerr;
if(chr == 'F')
chr = 'f';
if(prec > NSIGNIF)
prec = NSIGNIF;
if(prec < 0)
prec = 0;
if(__isNaN(f)) {
*decpt = 9999;
*rsign = 0;
strcpy(s1, "nan");
return &s1[3];
}
sign = 0;
if(f < 0) {
f = -f;
sign++;
}
*rsign = sign;
if(__isInf(f, 1) || __isInf(f, -1)) {
*decpt = 9999;
strcpy(s1, "inf");
return &s1[3];
}
e = 0;
g = f;
if(g != 0) {
frexp(f, &e);
e = (int)(e * .301029995664);
if(e >= -150 && e <= +150) {
d = 0;
h = f;
} else {
d = e/2;
h = f * pow10(-d);
}
g = h * pow10(d-e);
while(g < 1) {
e--;
g = h * pow10(d-e);
}
while(g >= 10) {
e++;
g = h * pow10(d-e);
}
}
/*
* convert NSIGNIF digits and convert
* back to get accuracy.
*/
for(i=0; i<NSIGNIF; i++) {
d = (int)g;
s1[i] = d + '0';
g = (g - d) * 10;
}
s1[i] = 0;
/*
* try decimal rounding to eliminate 9s
*/
c2 = prec + 1;
if(chr == 'f')
c2 += e;
oerr = errno;
if(c2 >= NSIGNIF-2) {
strcpy(s2, s1);
d = e;
s1[NSIGNIF-2] = '0';
s1[NSIGNIF-1] = '0';
xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
g = fmtstrtod(s1, nil);
if(g == f)
goto found;
if(xadd(s1, NSIGNIF-3, 1)) {
e++;
xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
}
g = fmtstrtod(s1, nil);
if(g == f)
goto found;
strcpy(s1, s2);
e = d;
}
/*
* convert back so s1 gets exact answer
*/
for(d = 0; d < 10; d++) {
xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
g = fmtstrtod(s1, nil);
if(f > g) {
if(xadd(s1, NSIGNIF-1, 1))
e--;
continue;
}
if(f < g) {
if(xsub(s1, NSIGNIF-1, 1))
e++;
continue;
}
break;
}
found:
errno = oerr;
/*
* sign
*/
d = 0;
i = 0;
/*
* round & adjust 'f' digits
*/
c2 = prec + 1;
if(chr == 'f'){
if(xadd(s1, c2+e, 5))
e++;
c2 += e;
if(c2 < 0){
c2 = 0;
e = -prec - 1;
}
}else{
if(xadd(s1, c2, 5))
e++;
}
if(c2 > NSIGNIF){
c2 = NSIGNIF;
}
*decpt = e + 1;
/*
* terminate the converted digits
*/
s1[c2] = '\0';
return &s1[c2];
}
/*
* this function works like the standard dtoa, if you want it.
*/
#if 0
static char*
__dtoa(double f, int mode, int ndigits, int *decpt, int *rsign, char **rve)
{
static char s2[NSIGNIF + 10];
char *es;
int chr, prec;
switch(mode) {
/* like 'e' */
case 2:
case 4:
case 6:
case 8:
chr = 'e';
break;
/* like 'g' */
case 0:
case 1:
default:
chr = 'g';
break;
/* like 'f' */
case 3:
case 5:
case 7:
case 9:
chr = 'f';
break;
}
if(chr != 'f' && ndigits){
ndigits--;
}
prec = ndigits;
if(prec > NSIGNIF)
prec = NSIGNIF;
if(ndigits == 0)
prec = NSIGNIF;
es = xdodtoa(s2, f, chr, prec, decpt, rsign);
/*
* strip trailing 0
*/
for(; es > s2 + 1; es--){
if(es[-1] != '0'){
break;
}
}
*es = '\0';
if(rve != NULL)
*rve = es;
return s2;
}
#endif
static int
fmtzdotpad(Fmt *f, int n, int pt)
{
char *t, *s;
int i;
Rune *rt, *rs;
if(f->runes){
rt = (Rune*)f->to;
rs = (Rune*)f->stop;
for(i = 0; i < n; i++){
if(i == pt){
FMTRCHAR(f, rt, rs, '.');
}
FMTRCHAR(f, rt, rs, '0');
}
f->nfmt += rt - (Rune*)f->to;
f->to = rt;
}else{
t = (char*)f->to;
s = (char*)f->stop;
for(i = 0; i < n; i++){
if(i == pt){
FMTCHAR(f, t, s, '.');
}
FMTCHAR(f, t, s, '0');
}
f->nfmt += t - (char *)f->to;
f->to = t;
}
return 0;
}
int
__efgfmt(Fmt *fmt)
{
double f;
char s1[NSIGNIF+10];
int e, d, n;
int c1, c2, c3, c4, ucase, sign, chr, prec, fl;
f = va_arg(fmt->args, double);
prec = FDEFLT;
fl = fmt->flags;
fmt->flags = 0;
if(fl & FmtPrec)
prec = fmt->prec;
chr = fmt->r;
ucase = 0;
if(chr == 'E'){
chr = 'e';
ucase = 1;
}else if(chr == 'F'){
chr = 'f';
ucase = 1;
}else if(chr == 'G'){
chr = 'g';
ucase = 1;
}
if(prec > 0 && chr == 'g')
prec--;
if(prec < 0)
prec = 0;
xdodtoa(s1, f, chr, prec, &e, &sign);
e--;
if(*s1 == 'i' || *s1 == 'n'){
if(ucase){
if(*s1 == 'i'){
strcpy(s1, "INF");
}else{
strcpy(s1, "NAN");
}
}
fmt->flags = fl & (FmtWidth|FmtLeft);
return __fmtcpy(fmt, (const void*)s1, 3, 3);
}
/*
* copy into final place
* c1 digits of leading '0'
* c2 digits from conversion
* c3 digits of trailing '0'
* c4 digits after '.'
*/
c1 = 0;
c2 = prec + 1;
c3 = 0;
c4 = prec;
switch(chr) {
default:
chr = 'e';
break;
case 'g':
/*
* decide on 'e' of 'f' style convers
*/
if(e >= -4 && e <= prec) {
c1 = -e;
c4 = prec - e;
chr = 'h'; /* flag for 'f' style */
}
break;
case 'f':
c1 = -e;
if(c1 > prec)
c1 = prec + 1;
c2 += e;
break;
}
/*
* clean up c1 c2 and c3
*/
if(c1 < 0)
c1 = 0;
if(c2 < 0)
c2 = 0;
if(c2 > NSIGNIF) {
c3 = c2-NSIGNIF;
c2 = NSIGNIF;
}
/*
* trim trailing zeros for %g
*/
if(!(fl & FmtSharp)
&& (chr == 'g' || chr == 'h')){
if(c4 >= c3){
c4 -= c3;
c3 = 0;
}else{
c3 -= c4;
c4 = 0;
}
while(c4 && c2 > 1 && s1[c2 - 1] == '0'){
c4--;
c2--;
}
}
/*
* calculate the total length
*/
n = c1 + c2 + c3;
if(sign || (fl & (FmtSign|FmtSpace)))
n++;
if(c4 || (fl & FmtSharp)){
n++;
}
if(chr == 'e' || chr == 'g'){
n += 4;
if(e >= 100)
n++;
}
/*
* pad to width if right justified
*/
if((fl & (FmtWidth|FmtLeft)) == FmtWidth && n < fmt->width){
if(fl & FmtZero){
c1 += fmt->width - n;
}else{
if(__fmtpad(fmt, fmt->width - n) < 0){
return -1;
}
}
}
/*
* sign
*/
d = 0;
if(sign)
d = '-';
else if(fl & FmtSign)
d = '+';
else if(fl & FmtSpace)
d = ' ';
if(d && fmtrune(fmt, d) < 0){
return -1;
}
/*
* copy digits
*/
c4 = c1 + c2 + c3 - c4;
if(c1 > 0){
if(fmtzdotpad(fmt, c1, c4) < 0){
return -1;
}
c4 -= c1;
}
d = 0;
if(c4 >= 0 && c4 < c2){
if(__fmtcpy(fmt, s1, c4, c4) < 0 || fmtrune(fmt, '.') < 0)
return -1;
d = c4;
c2 -= c4;
c4 = -1;
}
if(__fmtcpy(fmt, (const void*)(s1 + d), c2, c2) < 0){
return -1;
}
c4 -= c2;
if(c3 > 0){
if(fmtzdotpad(fmt, c3, c4) < 0){
return -1;
}
c4 -= c3;
}
/*
* strip trailing '0' on g conv
*/
if((fl & FmtSharp) && c4 == 0 && fmtrune(fmt, '.') < 0){
return -1;
}
if(chr == 'e' || chr == 'g') {
d = 0;
if(ucase)
s1[d++] = 'E';
else
s1[d++] = 'e';
c1 = e;
if(c1 < 0) {
s1[d++] = '-';
c1 = -c1;
} else
s1[d++] = '+';
if(c1 >= 100) {
s1[d++] = c1/100 + '0';
c1 = c1%100;
}
s1[d++] = c1/10 + '0';
s1[d++] = c1%10 + '0';
if(__fmtcpy(fmt, s1, d, d) < 0){
return -1;
}
}
if((fl & (FmtWidth|FmtLeft)) == (FmtWidth|FmtLeft) && n < fmt->width){
if(__fmtpad(fmt, fmt->width - n) < 0){
return -1;
}
}
return 0;
}

View File

@ -1,221 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
enum
{
Maxfmt = 64
};
typedef struct Convfmt Convfmt;
struct Convfmt
{
int c;
volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */
};
struct
{
/* lock by calling __fmtlock, __fmtunlock */
int nfmt;
Convfmt fmt[Maxfmt];
} fmtalloc;
static Convfmt knownfmt[] = {
' ', __flagfmt,
'#', __flagfmt,
'%', __percentfmt,
'+', __flagfmt,
',', __flagfmt,
'-', __flagfmt,
'C', __runefmt, /* Plan 9 addition */
'E', __efgfmt,
'F', __efgfmt, /* ANSI only */
'G', __efgfmt,
'L', __flagfmt, /* ANSI only */
'S', __runesfmt, /* Plan 9 addition */
'X', __ifmt,
'b', __ifmt, /* Plan 9 addition */
'c', __charfmt,
'd', __ifmt,
'e', __efgfmt,
'f', __efgfmt,
'g', __efgfmt,
'h', __flagfmt,
'i', __ifmt, /* ANSI only */
'l', __flagfmt,
'n', __countfmt,
'o', __ifmt,
'p', __ifmt,
'r', __errfmt,
's', __strfmt,
'u', __flagfmt, /* in Unix, __ifmt */
'x', __ifmt,
0, nil,
};
int (*fmtdoquote)(int);
/*
* __fmtlock() must be set
*/
static int
__fmtinstall(int c, Fmts f)
{
Convfmt *p, *ep;
if(c<=0 || c>=65536)
return -1;
if(!f)
f = __badfmt;
ep = &fmtalloc.fmt[fmtalloc.nfmt];
for(p=fmtalloc.fmt; p<ep; p++)
if(p->c == c)
break;
if(p == &fmtalloc.fmt[Maxfmt])
return -1;
p->fmt = f;
if(p == ep){ /* installing a new format character */
fmtalloc.nfmt++;
p->c = c;
}
return 0;
}
int
fmtinstall(int c, Fmts f)
{
int ret;
__fmtlock();
ret = __fmtinstall(c, f);
__fmtunlock();
return ret;
}
static Fmts
fmtfmt(int c)
{
Convfmt *p, *ep;
ep = &fmtalloc.fmt[fmtalloc.nfmt];
for(p=fmtalloc.fmt; p<ep; p++)
if(p->c == c){
while(p->fmt == nil) /* loop until value is updated */
;
return p->fmt;
}
/* is this a predefined format char? */
__fmtlock();
for(p=knownfmt; p->c; p++)
if(p->c == c){
__fmtinstall(p->c, p->fmt);
__fmtunlock();
return p->fmt;
}
__fmtunlock();
return __badfmt;
}
void*
__fmtdispatch(Fmt *f, void *fmt, int isrunes)
{
Rune rune, r;
int i, n;
f->flags = 0;
f->width = f->prec = 0;
for(;;){
if(isrunes){
r = *(Rune*)fmt;
fmt = (Rune*)fmt + 1;
}else{
fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
r = rune;
}
f->r = r;
switch(r){
case '\0':
return nil;
case '.':
f->flags |= FmtWidth|FmtPrec;
continue;
case '0':
if(!(f->flags & FmtWidth)){
f->flags |= FmtZero;
continue;
}
/* fall through */
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
i = 0;
while(r >= '0' && r <= '9'){
i = i * 10 + r - '0';
if(isrunes){
r = *(Rune*)fmt;
fmt = (Rune*)fmt + 1;
}else{
r = *(char*)fmt;
fmt = (char*)fmt + 1;
}
}
if(isrunes)
fmt = (Rune*)fmt - 1;
else
fmt = (char*)fmt - 1;
numflag:
if(f->flags & FmtWidth){
f->flags |= FmtPrec;
f->prec = i;
}else{
f->flags |= FmtWidth;
f->width = i;
}
continue;
case '*':
i = va_arg(f->args, int);
if(i < 0){
/*
* negative precision =>
* ignore the precision.
*/
if(f->flags & FmtPrec){
f->flags &= ~FmtPrec;
f->prec = 0;
continue;
}
i = -i;
f->flags |= FmtLeft;
}
goto numflag;
}
n = (*fmtfmt(r))(f);
if(n < 0)
return nil;
if(n == 0)
return fmt;
}
}

View File

@ -1,121 +0,0 @@
/*
* 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.
*/
/*
* dofmt -- format to a buffer
* the number of characters formatted is returned,
* or -1 if there was an error.
* if the buffer is ever filled, flush is called.
* it should reset the buffer and return whether formatting should continue.
*/
#define uchar _fmtuchar
#define ushort _fmtushort
#define uint _fmtuint
#define ulong _fmtulong
#define vlong _fmtvlong
#define uvlong _fmtuvlong
#define USED(x) if(x);else
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#ifndef NOVLONGS
typedef unsigned long long uvlong;
typedef long long vlong;
#endif
#define nil 0 /* cannot be ((void*)0) because used for function pointers */
typedef int (*Fmts)(Fmt*);
typedef struct Quoteinfo Quoteinfo;
struct Quoteinfo
{
int quoted; /* if set, string must be quoted */
int nrunesin; /* number of input runes that can be accepted */
int nbytesin; /* number of input bytes that can be accepted */
int nrunesout; /* number of runes that will be generated */
int nbytesout; /* number of bytes that will be generated */
};
void *__fmtflush(Fmt*, void*, int);
void *__fmtdispatch(Fmt*, void*, int);
int __floatfmt(Fmt*, double);
int __fmtpad(Fmt*, int);
int __rfmtpad(Fmt*, int);
int __fmtFdFlush(Fmt*);
int __efgfmt(Fmt*);
int __charfmt(Fmt*);
int __runefmt(Fmt*);
int __runesfmt(Fmt*);
int __countfmt(Fmt*);
int __flagfmt(Fmt*);
int __percentfmt(Fmt*);
int __ifmt(Fmt*);
int __strfmt(Fmt*);
int __badfmt(Fmt*);
int __fmtcpy(Fmt*, const void*, int, int);
int __fmtrcpy(Fmt*, const void*, int n);
int __errfmt(Fmt *f);
double __fmtpow10(int);
void __fmtlock(void);
void __fmtunlock(void);
#define FMTCHAR(f, t, s, c)\
do{\
if(t + 1 > (char*)s){\
t = __fmtflush(f, t, 1);\
if(t != nil)\
s = f->stop;\
else\
return -1;\
}\
*t++ = c;\
}while(0)
#define FMTRCHAR(f, t, s, c)\
do{\
if(t + 1 > (Rune*)s){\
t = __fmtflush(f, t, sizeof(Rune));\
if(t != nil)\
s = f->stop;\
else\
return -1;\
}\
*t++ = c;\
}while(0)
#define FMTRUNE(f, t, s, r)\
do{\
Rune _rune;\
int _runelen;\
if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\
t = __fmtflush(f, t, _runelen);\
if(t != nil)\
s = f->stop;\
else\
return -1;\
}\
if(r < Runeself)\
*t++ = r;\
else{\
_rune = r;\
t += runetochar(t, &_rune);\
}\
}while(0)

View File

@ -1,46 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/*
* public routine for final flush of a formatting buffer
* to a file descriptor; returns total char count.
*/
int
fmtfdflush(Fmt *f)
{
if(__fmtFdFlush(f) <= 0)
return -1;
return f->nfmt;
}
/*
* initialize an output buffer for buffered printing
*/
int
fmtfdinit(Fmt *f, int fd, char *buf, int size)
{
f->runes = 0;
f->start = buf;
f->to = buf;
f->stop = buf + size;
f->flush = __fmtFdFlush;
f->farg = (void*)fd;
f->nfmt = 0;
return 0;
}

View File

@ -1,33 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <unistd.h>
#include "fmt.h"
#include "fmtdef.h"
/*
* generic routine for flushing a formatting buffer
* to a file descriptor
*/
int
__fmtFdFlush(Fmt *f)
{
int n;
n = (char*)f->to - (char*)f->start;
if(n && write((int)f->farg, f->start, n) != n)
return 0;
f->to = f->start;
return 1;
}

View File

@ -1,28 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "fmt.h"
#include "fmtdef.h"
void
__fmtlock(void)
{
;
}
void
__fmtunlock(void)
{
;
}

View File

@ -1,47 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/*
* format a string into the output buffer
* designed for formats which themselves call fmt,
* but ignore any width flags
*/
int
fmtprint(Fmt *f, char *fmt, ...)
{
va_list va;
int n;
f->flags = 0;
f->width = 0;
f->prec = 0;
va = f->args;
va_start(f->args, fmt);
n = dofmt(f, fmt);
va_end(f->args);
f->flags = 0;
f->width = 0;
f->prec = 0;
f->args = va;
if(n >= 0)
return 0;
return n;
}

View File

@ -1,262 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/*
* How many bytes of output UTF will be produced by quoting (if necessary) this string?
* How many runes? How much of the input will be consumed?
* The parameter q is filled in by __quotesetup.
* The string may be UTF or Runes (s or r).
* Return count does not include NUL.
* Terminate the scan at the first of:
* NUL in input
* count exceeded in input
* count exceeded on output
* *ninp is set to number of input bytes accepted.
* nin may be <0 initially, to avoid checking input by count.
*/
void
__quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout)
{
int w;
Rune c;
q->quoted = 0;
q->nbytesout = 0;
q->nrunesout = 0;
q->nbytesin = 0;
q->nrunesin = 0;
if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){
if(nout < 2)
return;
q->quoted = 1;
q->nbytesout = 2;
q->nrunesout = 2;
}
for(; nin!=0; nin-=w){
if(s)
w = chartorune(&c, s);
else{
c = *r;
w = runelen(c);
}
if(c == '\0')
break;
if(runesout){
if(q->nrunesout+1 > nout)
break;
}else{
if(q->nbytesout+w > nout)
break;
}
if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){
if(!q->quoted){
if(runesout){
if(1+q->nrunesout+1+1 > nout) /* no room for quotes */
break;
}else{
if(1+q->nbytesout+w+1 > nout) /* no room for quotes */
break;
}
q->nrunesout += 2; /* include quotes */
q->nbytesout += 2; /* include quotes */
q->quoted = 1;
}
if(c == '\'') {
if(runesout){
if(1+q->nrunesout+1 > nout) /* no room for quotes */
break;
}else{
if(1+q->nbytesout+w > nout) /* no room for quotes */
break;
}
q->nbytesout++;
q->nrunesout++; /* quotes reproduce as two characters */
}
}
/* advance input */
if(s)
s += w;
else
r++;
q->nbytesin += w;
q->nrunesin++;
/* advance output */
q->nbytesout += w;
q->nrunesout++;
}
}
static int
qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f)
{
Rune r, *rm, *rme;
char *t, *s, *m, *me;
Rune *rt, *rs;
ulong fl;
int nc, w;
m = sin;
me = m + q->nbytesin;
rm = rin;
rme = rm + q->nrunesin;
w = f->width;
fl = f->flags;
if(f->runes){
if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0)
return -1;
}else{
if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
return -1;
}
t = (char*)f->to;
s = (char*)f->stop;
rt = (Rune*)f->to;
rs = (Rune*)f->stop;
if(f->runes)
FMTRCHAR(f, rt, rs, '\'');
else
FMTRUNE(f, t, s, '\'');
for(nc = q->nrunesin; nc > 0; nc--){
if(sin){
r = *(uchar*)m;
if(r < Runeself)
m++;
else if((me - m) >= UTFmax || fullrune(m, me-m))
m += chartorune(&r, m);
else
break;
}else{
if(rm >= rme)
break;
r = *(uchar*)rm++;
}
if(f->runes){
FMTRCHAR(f, rt, rs, r);
if(r == '\'')
FMTRCHAR(f, rt, rs, r);
}else{
FMTRUNE(f, t, s, r);
if(r == '\'')
FMTRUNE(f, t, s, r);
}
}
if(f->runes){
FMTRCHAR(f, rt, rs, '\'');
USED(rs);
f->nfmt += rt - (Rune *)f->to;
f->to = rt;
if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0)
return -1;
}else{
FMTRUNE(f, t, s, '\'');
USED(s);
f->nfmt += t - (char *)f->to;
f->to = t;
if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
return -1;
}
return 0;
}
int
__quotestrfmt(int runesin, Fmt *f)
{
int outlen;
Rune *r;
char *s;
Quoteinfo q;
f->flags &= ~FmtPrec; /* ignored for %q %Q, so disable for %s %S in easy case */
if(runesin){
r = va_arg(f->args, Rune *);
s = nil;
}else{
s = va_arg(f->args, char *);
r = nil;
}
if(!s && !r)
return __fmtcpy(f, (void*)"<nil>", 5, 5);
if(f->flush)
outlen = 0x7FFFFFFF; /* if we can flush, no output limit */
else if(f->runes)
outlen = (Rune*)f->stop - (Rune*)f->to;
else
outlen = (char*)f->stop - (char*)f->to;
__quotesetup(s, r, -1, outlen, &q, f->flags&FmtSharp, f->runes);
//print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout);
if(runesin){
if(!q.quoted)
return __fmtrcpy(f, r, q.nrunesin);
return qstrfmt(nil, r, &q, f);
}
if(!q.quoted)
return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
return qstrfmt(s, nil, &q, f);
}
int
quotestrfmt(Fmt *f)
{
return __quotestrfmt(0, f);
}
int
quoterunestrfmt(Fmt *f)
{
return __quotestrfmt(1, f);
}
void
quotefmtinstall(void)
{
fmtinstall('q', quotestrfmt);
fmtinstall('Q', quoterunestrfmt);
}
int
__needsquotes(char *s, int *quotelenp)
{
Quoteinfo q;
__quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
*quotelenp = q.nbytesout;
return q.quoted;
}
int
__runeneedsquotes(Rune *r, int *quotelenp)
{
Quoteinfo q;
__quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
*quotelenp = q.nrunesout;
return q.quoted;
}

View File

@ -1,40 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
int
fmtrune(Fmt *f, int r)
{
Rune *rt;
char *t;
int n;
if(f->runes){
rt = (Rune*)f->to;
FMTRCHAR(f, rt, f->stop, r);
f->to = rt;
n = 1;
}else{
t = (char*)f->to;
FMTRUNE(f, t, f->stop, r);
n = t - (char*)f->to;
f->to = t;
}
f->nfmt += n;
return 0;
}

View File

@ -1,65 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
static int
fmtStrFlush(Fmt *f)
{
char *s;
int n;
n = (int)f->farg;
n += 256;
f->farg = (void*)n;
s = (char*)f->start;
f->start = realloc(s, n);
if(f->start == nil){
f->start = s;
return 0;
}
f->to = (char*)f->start + ((char*)f->to - s);
f->stop = (char*)f->start + n - 1;
return 1;
}
int
fmtstrinit(Fmt *f)
{
int n;
f->runes = 0;
n = 32;
f->start = malloc(n);
if(f->start == nil)
return -1;
f->to = f->start;
f->stop = (char*)f->start + n - 1;
f->flush = fmtStrFlush;
f->farg = (void*)n;
f->nfmt = 0;
return 0;
}
char*
fmtstrflush(Fmt *f)
{
*(char*)f->to = '\0';
f->to = f->start;
return (char*)f->start;
}

View File

@ -1,46 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/*
* format a string into the output buffer
* designed for formats which themselves call fmt,
* but ignore any width flags
*/
int
fmtvprint(Fmt *f, char *fmt, va_list args)
{
va_list va;
int n;
f->flags = 0;
f->width = 0;
f->prec = 0;
va = f->args;
f->args = args;
n = dofmt(f, fmt);
f->flags = 0;
f->width = 0;
f->prec = 0;
f->args = va;
if(n >= 0)
return 0;
return n;
}

View File

@ -1,28 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "utf.h"
#include "fmt.h"
int
fprint(int fd, char *fmt, ...)
{
int n;
va_list args;
va_start(args, fmt);
n = vfprint(fd, fmt, args);
va_end(args);
return n;
}

View File

@ -1,57 +0,0 @@
PLAN9=../..
<$PLAN9/src/mkhdr
LIB=libfmt.a
NUM=\
charstod.$O\
pow10.$O\
# Could add errfmt, but we want to pick it up from lib9 instead.
OFILES=\
dofmt.$O\
errfmt.$O\
fltfmt.$O\
fmt.$O\
fmtfd.$O\
fmtfdflush.$O\
fmtlock.$O\
fmtprint.$O\
fmtquote.$O\
fmtrune.$O\
fmtstr.$O\
fmtvprint.$O\
fprint.$O\
nan64.$O\
print.$O\
runefmtstr.$O\
runeseprint.$O\
runesmprint.$O\
runesnprint.$O\
runesprint.$O\
runevseprint.$O\
runevsmprint.$O\
runevsnprint.$O\
seprint.$O\
smprint.$O\
snprint.$O\
sprint.$O\
strtod.$O\
vfprint.$O\
vseprint.$O\
vsmprint.$O\
vsnprint.$O\
$NUM\
HFILES=\
fmtdef.h\
$PLAN9/include/fmt.h\
<$PLAN9/src/mksyslib
$NAN.$O: nan.h
strtod.$O: nan.h
test: $LIB test.$O
$CC -o test test.$O $LIB -L$PLAN9/lib -lutf

View File

@ -1,4 +0,0 @@
extern double __NaN(void);
extern double __Inf(int);
extern int __isNaN(double);
extern int __isInf(double, int);

View File

@ -1,76 +0,0 @@
/*
* 64-bit IEEE not-a-number routines.
* This is big/little-endian portable assuming that
* the 64-bit doubles and 64-bit integers have the
* same byte ordering.
*/
#include "nan.h"
#ifdef __APPLE__
#define _NEEDLL
#endif
typedef unsigned long long uvlong;
typedef unsigned long ulong;
#ifdef _NEEDLL
static uvlong uvnan = 0x7FF0000000000001LL;
static uvlong uvinf = 0x7FF0000000000000LL;
static uvlong uvneginf = 0xFFF0000000000000LL;
#else
static uvlong uvnan = 0x7FF0000000000001;
static uvlong uvinf = 0x7FF0000000000000;
static uvlong uvneginf = 0xFFF0000000000000;
#endif
double
__NaN(void)
{
uvlong *p;
/* gcc complains about "return *(double*)&uvnan;" */
p = &uvnan;
return *(double*)p;
}
int
__isNaN(double d)
{
uvlong x;
double *p;
p = &d;
x = *(uvlong*)p;
return (ulong)(x>>32)==0x7FF00000 && !__isInf(d, 0);
}
double
__Inf(int sign)
{
uvlong *p;
if(sign < 0)
p = &uvinf;
else
p = &uvneginf;
return *(double*)p;
}
int
__isInf(double d, int sign)
{
uvlong x;
double *p;
p = &d;
x = *(uvlong*)p;
if(sign == 0)
return x==uvinf || x==uvneginf;
else if(sign > 0)
return x==uvinf;
else
return x==uvneginf;
}

View File

@ -1,57 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/*
* this table might overflow 127-bit exponent representations.
* in that case, truncate it after 1.0e38.
* it is important to get all one can from this
* routine since it is used in atof to scale numbers.
* the presumption is that C converts fp numbers better
* than multipication of lower powers of 10.
*/
static
double tab[] =
{
1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
1.0e10,1.0e11,1.0e12,1.0e13,1.0e14,1.0e15,1.0e16,1.0e17,1.0e18,1.0e19,
1.0e20,1.0e21,1.0e22,1.0e23,1.0e24,1.0e25,1.0e26,1.0e27,1.0e28,1.0e29,
1.0e30,1.0e31,1.0e32,1.0e33,1.0e34,1.0e35,1.0e36,1.0e37,1.0e38,1.0e39,
1.0e40,1.0e41,1.0e42,1.0e43,1.0e44,1.0e45,1.0e46,1.0e47,1.0e48,1.0e49,
1.0e50,1.0e51,1.0e52,1.0e53,1.0e54,1.0e55,1.0e56,1.0e57,1.0e58,1.0e59,
1.0e60,1.0e61,1.0e62,1.0e63,1.0e64,1.0e65,1.0e66,1.0e67,1.0e68,1.0e69,
};
double
__fmtpow10(int n)
{
int m;
if(n < 0) {
n = -n;
if(n < (int)(sizeof(tab)/sizeof(tab[0])))
return 1/tab[n];
m = n/2;
return __fmtpow10(-m) * __fmtpow10(m-n);
}
if(n < (int)(sizeof(tab)/sizeof(tab[0])))
return tab[n];
m = n/2;
return __fmtpow10(m) * __fmtpow10(n-m);
}

View File

@ -1,469 +0,0 @@
.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 .

View File

@ -1,28 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "utf.h"
#include "fmt.h"
int
print(char *fmt, ...)
{
int n;
va_list args;
va_start(args, fmt);
n = vfprint(1, fmt, args);
va_end(args);
return n;
}

View File

@ -1,65 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
static int
runeFmtStrFlush(Fmt *f)
{
Rune *s;
int n;
n = (int)f->farg;
n += 256;
f->farg = (void*)n;
s = (Rune*)f->start;
f->start = realloc(s, sizeof(Rune)*n);
if(f->start == nil){
f->start = s;
return 0;
}
f->to = (Rune*)f->start + ((Rune*)f->to - s);
f->stop = (Rune*)f->start + n - 1;
return 1;
}
int
runefmtstrinit(Fmt *f)
{
int n;
f->runes = 1;
n = 32;
f->start = malloc(sizeof(Rune)*n);
if(f->start == nil)
return -1;
f->to = f->start;
f->stop = (Rune*)f->start + n - 1;
f->flush = runeFmtStrFlush;
f->farg = (void*)n;
f->nfmt = 0;
return 0;
}
Rune*
runefmtstrflush(Fmt *f)
{
*(Rune*)f->to = '\0';
f->to = f->start;
return f->start;
}

View File

@ -1,30 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
Rune*
runeseprint(Rune *buf, Rune *e, char *fmt, ...)
{
Rune *p;
va_list args;
va_start(args, fmt);
p = runevseprint(buf, e, fmt, args);
va_end(args);
return p;
}

View File

@ -1,30 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
Rune*
runesmprint(char *fmt, ...)
{
va_list args;
Rune *p;
va_start(args, fmt);
p = runevsmprint(fmt, args);
va_end(args);
return p;
}

View File

@ -1,31 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
int
runesnprint(Rune *buf, int len, char *fmt, ...)
{
int n;
va_list args;
va_start(args, fmt);
n = runevsnprint(buf, len, fmt, args);
va_end(args);
return n;
}

View File

@ -1,30 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
int
runesprint(Rune *buf, char *fmt, ...)
{
int n;
va_list args;
va_start(args, fmt);
n = runevsnprint(buf, 256, fmt, args);
va_end(args);
return n;
}

View File

@ -1,39 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
Rune*
runevseprint(Rune *buf, Rune *e, char *fmt, va_list args)
{
Fmt f;
if(e <= buf)
return nil;
f.runes = 1;
f.start = buf;
f.to = buf;
f.stop = e - 1;
f.flush = nil;
f.farg = nil;
f.nfmt = 0;
f.args = args;
dofmt(&f, fmt);
*(Rune*)f.to = '\0';
return (Rune*)f.to;
}

View File

@ -1,37 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <stdlib.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
/*
* print into an allocated string buffer
*/
Rune*
runevsmprint(char *fmt, va_list args)
{
Fmt f;
int n;
if(runefmtstrinit(&f) < 0)
return nil;
f.args = args;
n = dofmt(&f, fmt);
if(n < 0)
return nil;
*(Rune*)f.to = '\0';
return (Rune*)f.start;
}

View File

@ -1,38 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "fmt.h"
#include "fmtdef.h"
int
runevsnprint(Rune *buf, int len, char *fmt, va_list args)
{
Fmt f;
if(len <= 0)
return -1;
f.runes = 1;
f.start = buf;
f.to = buf;
f.stop = buf + len - 1;
f.flush = nil;
f.farg = nil;
f.nfmt = 0;
f.args = args;
dofmt(&f, fmt);
*(Rune*)f.to = '\0';
return (Rune*)f.to - buf;
}

View File

@ -1,27 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "fmt.h"
char*
seprint(char *buf, char *e, char *fmt, ...)
{
char *p;
va_list args;
va_start(args, fmt);
p = vseprint(buf, e, fmt, args);
va_end(args);
return p;
}

View File

@ -1,27 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "fmt.h"
char*
smprint(char *fmt, ...)
{
va_list args;
char *p;
va_start(args, fmt);
p = vsmprint(fmt, args);
va_end(args);
return p;
}

View File

@ -1,28 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "fmt.h"
int
snprint(char *buf, int len, char *fmt, ...)
{
int n;
va_list args;
va_start(args, fmt);
n = vsnprint(buf, len, fmt, args);
va_end(args);
return n;
}

View File

@ -1,27 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "fmt.h"
int
sprint(char *buf, char *fmt, ...)
{
int n;
va_list args;
va_start(args, fmt);
n = vsnprint(buf, 65536, fmt, args); /* big number, but sprint is deprecated anyway */
va_end(args);
return n;
}

View File

@ -1,539 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "fmt.h"
#include "nan.h"
#ifndef nelem
#define nelem(x) (sizeof(x)/sizeof *(x))
#endif
#define nil ((void*)0)
#define ulong _fmtulong
typedef unsigned long ulong;
static ulong
umuldiv(ulong a, ulong b, ulong c)
{
double d;
d = ((double)a * (double)b) / (double)c;
if(d >= 4294967295.)
d = 4294967295.;
return (ulong)d;
}
/*
* This routine will convert to arbitrary precision
* floating point entirely in multi-precision fixed.
* The answer is the closest floating point number to
* the given decimal number. Exactly half way are
* rounded ala ieee rules.
* Method is to scale input decimal between .500 and .999...
* with external power of 2, then binary search for the
* closest mantissa to this decimal number.
* Nmant is is the required precision. (53 for ieee dp)
* Nbits is the max number of bits/word. (must be <= 28)
* Prec is calculated - the number of words of fixed mantissa.
*/
enum
{
Nbits = 28, /* bits safely represented in a ulong */
Nmant = 53, /* bits of precision required */
Prec = (Nmant+Nbits+1)/Nbits, /* words of Nbits each to represent mantissa */
Sigbit = 1<<(Prec*Nbits-Nmant), /* first significant bit of Prec-th word */
Ndig = 1500,
One = (ulong)(1<<Nbits),
Half = (ulong)(One>>1),
Maxe = 310,
Fsign = 1<<0, /* found - */
Fesign = 1<<1, /* found e- */
Fdpoint = 1<<2, /* found . */
S0 = 0, /* _ _S0 +S1 #S2 .S3 */
S1, /* _+ #S2 .S3 */
S2, /* _+# #S2 .S4 eS5 */
S3, /* _+. #S4 */
S4, /* _+#.# #S4 eS5 */
S5, /* _+#.#e +S6 #S7 */
S6, /* _+#.#e+ #S7 */
S7, /* _+#.#e+# #S7 */
};
static int xcmp(char*, char*);
static int fpcmp(char*, ulong*);
static void frnorm(ulong*);
static void divascii(char*, int*, int*, int*);
static void mulascii(char*, int*, int*, int*);
typedef struct Tab Tab;
struct Tab
{
int bp;
int siz;
char* cmp;
};
double
fmtstrtod(const char *as, char **aas)
{
int na, ex, dp, bp, c, i, flag, state;
ulong low[Prec], hig[Prec], mid[Prec];
double d;
char *s, a[Ndig];
flag = 0; /* Fsign, Fesign, Fdpoint */
na = 0; /* number of digits of a[] */
dp = 0; /* na of decimal point */
ex = 0; /* exonent */
state = S0;
for(s=(char*)as;; s++) {
c = *s;
if(c >= '0' && c <= '9') {
switch(state) {
case S0:
case S1:
case S2:
state = S2;
break;
case S3:
case S4:
state = S4;
break;
case S5:
case S6:
case S7:
state = S7;
ex = ex*10 + (c-'0');
continue;
}
if(na == 0 && c == '0') {
dp--;
continue;
}
if(na < Ndig-50)
a[na++] = c;
continue;
}
switch(c) {
case '\t':
case '\n':
case '\v':
case '\f':
case '\r':
case ' ':
if(state == S0)
continue;
break;
case '-':
if(state == S0)
flag |= Fsign;
else
flag |= Fesign;
case '+':
if(state == S0)
state = S1;
else
if(state == S5)
state = S6;
else
break; /* syntax */
continue;
case '.':
flag |= Fdpoint;
dp = na;
if(state == S0 || state == S1) {
state = S3;
continue;
}
if(state == S2) {
state = S4;
continue;
}
break;
case 'e':
case 'E':
if(state == S2 || state == S4) {
state = S5;
continue;
}
break;
}
break;
}
/*
* clean up return char-pointer
*/
switch(state) {
case S0:
if(xcmp(s, "nan") == 0) {
if(aas != nil)
*aas = s+3;
goto retnan;
}
case S1:
if(xcmp(s, "infinity") == 0) {
if(aas != nil)
*aas = s+8;
goto retinf;
}
if(xcmp(s, "inf") == 0) {
if(aas != nil)
*aas = s+3;
goto retinf;
}
case S3:
if(aas != nil)
*aas = (char*)as;
goto ret0; /* no digits found */
case S6:
s--; /* back over +- */
case S5:
s--; /* back over e */
break;
}
if(aas != nil)
*aas = s;
if(flag & Fdpoint)
while(na > 0 && a[na-1] == '0')
na--;
if(na == 0)
goto ret0; /* zero */
a[na] = 0;
if(!(flag & Fdpoint))
dp = na;
if(flag & Fesign)
ex = -ex;
dp += ex;
if(dp < -Maxe){
errno = ERANGE;
goto ret0; /* underflow by exp */
} else
if(dp > +Maxe)
goto retinf; /* overflow by exp */
/*
* normalize the decimal ascii number
* to range .[5-9][0-9]* e0
*/
bp = 0; /* binary exponent */
while(dp > 0)
divascii(a, &na, &dp, &bp);
while(dp < 0 || a[0] < '5')
mulascii(a, &na, &dp, &bp);
/* close approx by naive conversion */
mid[0] = 0;
mid[1] = 1;
for(i=0; c=a[i]; i++) {
mid[0] = mid[0]*10 + (c-'0');
mid[1] = mid[1]*10;
if(i >= 8)
break;
}
low[0] = umuldiv(mid[0], One, mid[1]);
hig[0] = umuldiv(mid[0]+1, One, mid[1]);
for(i=1; i<Prec; i++) {
low[i] = 0;
hig[i] = One-1;
}
/* binary search for closest mantissa */
for(;;) {
/* mid = (hig + low) / 2 */
c = 0;
for(i=0; i<Prec; i++) {
mid[i] = hig[i] + low[i];
if(c)
mid[i] += One;
c = mid[i] & 1;
mid[i] >>= 1;
}
frnorm(mid);
/* compare */
c = fpcmp(a, mid);
if(c > 0) {
c = 1;
for(i=0; i<Prec; i++)
if(low[i] != mid[i]) {
c = 0;
low[i] = mid[i];
}
if(c)
break; /* between mid and hig */
continue;
}
if(c < 0) {
for(i=0; i<Prec; i++)
hig[i] = mid[i];
continue;
}
/* only hard part is if even/odd roundings wants to go up */
c = mid[Prec-1] & (Sigbit-1);
if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0)
mid[Prec-1] -= c;
break; /* exactly mid */
}
/* normal rounding applies */
c = mid[Prec-1] & (Sigbit-1);
mid[Prec-1] -= c;
if(c >= Sigbit/2) {
mid[Prec-1] += Sigbit;
frnorm(mid);
}
goto out;
ret0:
return 0;
retnan:
return __NaN();
retinf:
/*
* Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */
errno = ERANGE;
if(flag & Fsign)
return -HUGE_VAL;
return HUGE_VAL;
out:
d = 0;
for(i=0; i<Prec; i++)
d = d*One + mid[i];
if(flag & Fsign)
d = -d;
d = ldexp(d, bp - Prec*Nbits);
if(d == 0){ /* underflow */
errno = ERANGE;
}
return d;
}
static void
frnorm(ulong *f)
{
int i, c;
c = 0;
for(i=Prec-1; i>0; i--) {
f[i] += c;
c = f[i] >> Nbits;
f[i] &= One-1;
}
f[0] += c;
}
static int
fpcmp(char *a, ulong* f)
{
ulong tf[Prec];
int i, d, c;
for(i=0; i<Prec; i++)
tf[i] = f[i];
for(;;) {
/* tf *= 10 */
for(i=0; i<Prec; i++)
tf[i] = tf[i]*10;
frnorm(tf);
d = (tf[0] >> Nbits) + '0';
tf[0] &= One-1;
/* compare next digit */
c = *a;
if(c == 0) {
if('0' < d)
return -1;
if(tf[0] != 0)
goto cont;
for(i=1; i<Prec; i++)
if(tf[i] != 0)
goto cont;
return 0;
}
if(c > d)
return +1;
if(c < d)
return -1;
a++;
cont:;
}
return 0;
}
static void
divby(char *a, int *na, int b)
{
int n, c;
char *p;
p = a;
n = 0;
while(n>>b == 0) {
c = *a++;
if(c == 0) {
while(n) {
c = n*10;
if(c>>b)
break;
n = c;
}
goto xx;
}
n = n*10 + c-'0';
(*na)--;
}
for(;;) {
c = n>>b;
n -= c<<b;
*p++ = c + '0';
c = *a++;
if(c == 0)
break;
n = n*10 + c-'0';
}
(*na)++;
xx:
while(n) {
n = n*10;
c = n>>b;
n -= c<<b;
*p++ = c + '0';
(*na)++;
}
*p = 0;
}
static Tab tab1[] =
{
1, 0, "",
3, 1, "7",
6, 2, "63",
9, 3, "511",
13, 4, "8191",
16, 5, "65535",
19, 6, "524287",
23, 7, "8388607",
26, 8, "67108863",
27, 9, "134217727",
};
static void
divascii(char *a, int *na, int *dp, int *bp)
{
int b, d;
Tab *t;
d = *dp;
if(d >= (int)(nelem(tab1)))
d = (int)(nelem(tab1))-1;
t = tab1 + d;
b = t->bp;
if(memcmp(a, t->cmp, t->siz) > 0)
d--;
*dp -= d;
*bp += b;
divby(a, na, b);
}
static void
mulby(char *a, char *p, char *q, int b)
{
int n, c;
n = 0;
*p = 0;
for(;;) {
q--;
if(q < a)
break;
c = *q - '0';
c = (c<<b) + n;
n = c/10;
c -= n*10;
p--;
*p = c + '0';
}
while(n) {
c = n;
n = c/10;
c -= n*10;
p--;
*p = c + '0';
}
}
static Tab tab2[] =
{
1, 1, "", /* dp = 0-0 */
3, 3, "125",
6, 5, "15625",
9, 7, "1953125",
13, 10, "1220703125",
16, 12, "152587890625",
19, 14, "19073486328125",
23, 17, "11920928955078125",
26, 19, "1490116119384765625",
27, 19, "7450580596923828125", /* dp 8-9 */
};
static void
mulascii(char *a, int *na, int *dp, int *bp)
{
char *p;
int d, b;
Tab *t;
d = -*dp;
if(d >= (int)(nelem(tab2)))
d = (int)(nelem(tab2))-1;
t = tab2 + d;
b = t->bp;
if(memcmp(a, t->cmp, t->siz) < 0)
d--;
p = a + *na;
*bp -= b;
*dp += d;
*na += d;
mulby(a, p+d, p, b);
}
static int
xcmp(char *a, char *b)
{
int c1, c2;
while(c1 = *b++) {
c2 = *a++;
if(isupper(c2))
c2 = tolower(c2);
if(c1 != c2)
return 1;
}
return 0;
}

View File

@ -1,4 +0,0 @@
extern double __NaN(void);
extern double __Inf(int);
extern double __isNaN(double);
extern double __isInf(double, int);

View File

@ -1,39 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <utf.h>
#include "fmt.h"
int
main(int argc, char *argv[])
{
quotefmtinstall();
print("hello world\n");
print("x: %x\n", 0x87654321);
print("u: %u\n", 0x87654321);
print("d: %d\n", 0x87654321);
print("s: %s\n", "hi there");
print("q: %q\n", "hi i'm here");
print("c: %c\n", '!');
print("g: %g %g %g\n", 3.14159, 3.14159e10, 3.14159e-10);
print("e: %e %e %e\n", 3.14159, 3.14159e10, 3.14159e-10);
print("f: %f %f %f\n", 3.14159, 3.14159e10, 3.14159e-10);
print("smiley: %C\n", (Rune)0x263a);
print("%g %.18\n", 2e25, 2e25);
print("%2.18g\n", 1.0);
print("%f\n", 3.1415927/4);
print("%d\n", 23);
print("%i\n", 23);
return 0;
}

View File

@ -1,31 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "fmt.h"
#include "fmtdef.h"
int
vfprint(int fd, char *fmt, va_list args)
{
Fmt f;
char buf[256];
int n;
fmtfdinit(&f, fd, buf, sizeof(buf));
f.args = args;
n = dofmt(&f, fmt);
if(n > 0 && __fmtFdFlush(&f) == 0)
return -1;
return n;
}

View File

@ -1,37 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include "fmt.h"
#include "fmtdef.h"
char*
vseprint(char *buf, char *e, char *fmt, va_list args)
{
Fmt f;
if(e <= buf)
return nil;
f.runes = 0;
f.start = buf;
f.to = buf;
f.stop = e - 1;
f.flush = 0;
f.farg = nil;
f.nfmt = 0;
f.args = args;
dofmt(&f, fmt);
*(char*)f.to = '\0';
return (char*)f.to;
}

View File

@ -1,36 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdlib.h>
#include <stdarg.h>
#include "fmt.h"
#include "fmtdef.h"
/*
* print into an allocated string buffer
*/
char*
vsmprint(char *fmt, va_list args)
{
Fmt f;
int n;
if(fmtstrinit(&f) < 0)
return nil;
f.args = args;
n = dofmt(&f, fmt);
if(n < 0)
return nil;
*(char*)f.to = '\0';
return (char*)f.start;
}

View File

@ -1,37 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdlib.h>
#include <stdarg.h>
#include "fmt.h"
#include "fmtdef.h"
int
vsnprint(char *buf, int len, char *fmt, va_list args)
{
Fmt f;
if(len <= 0)
return -1;
f.runes = 0;
f.start = buf;
f.to = buf;
f.stop = buf + len - 1;
f.flush = 0;
f.farg = nil;
f.nfmt = 0;
f.args = args;
dofmt(&f, fmt);
*(char*)f.to = '\0';
return (char*)f.to - buf;
}

View File

@ -5,6 +5,7 @@
#include <libc.h>
#include <fcall.h>
#include <fs.h>
#include <thread.h>
#include "fsimpl.h"
static int _fssend(Mux*, void*);
@ -270,7 +271,7 @@ _fsrecv(Mux *mux)
Fsys *fs;
fs = mux->aux;
n = readn(fs->fd, buf, 4);
n = threadreadn(fs->fd, buf, 4);
if(n != 4)
return nil;
n = GBIT32(buf);
@ -280,12 +281,12 @@ _fsrecv(Mux *mux)
return nil;
}
PBIT32(pkt, n);
if(readn(fs->fd, pkt+4, n-4) != n-4){
if(threadreadn(fs->fd, pkt+4, n-4) != n-4){
free(pkt);
return nil;
}
if(pkt[4] == Ropenfd){
if((nfd=recvfd(fs->fd)) < 0){
if((nfd=threadrecvfd(fs->fd)) < 0){
fprint(2, "recv fd error: %r\n");
free(pkt);
return nil;

View File

@ -12,7 +12,12 @@ fspread(Fid *fid, void *buf, long n, vlong offset)
{
Fcall tx, rx;
void *freep;
uint msize;
msize = fid->fs->msize - IOHDRSZ;
fprint(2, "n %d msize %d\n", n, msize);
if(n > msize)
n = msize;
tx.type = Tread;
tx.fid = fid->fid;
if(offset == -1){

View File

@ -7,8 +7,8 @@
#include <fs.h>
#include "fsimpl.h"
long
fspwrite(Fid *fid, void *buf, long n, vlong offset)
static long
_fspwrite(Fid *fid, void *buf, long n, vlong offset)
{
Fcall tx, rx;
void *freep;
@ -39,6 +39,31 @@ fspwrite(Fid *fid, void *buf, long n, vlong offset)
return rx.count;
}
long
fspwrite(Fid *fid, void *buf, long n, vlong offset)
{
long tot, want, got;
uint msize;
msize = fid->fs->msize - IOHDRSZ;
tot = 0;
while(tot < n){
want = n - tot;
if(want > msize)
want = msize;
got = _fspwrite(fid, buf, want, offset);
if(got < 0){
if(tot == 0)
return got;
break;
}
tot += got;
if(offset != -1)
offset += got;
}
return tot;
}
long
fswrite(Fid *fid, void *buf, long n)
{

View File

@ -5,6 +5,7 @@ LIB=libplumb.a
OFILES=\
event.$O\
mesg.$O\
thread.$O\
HFILES=$PLAN9/include/plumb.h

View File

@ -65,9 +65,7 @@ chaninit(Channel *c, int elemsize, int elemcnt)
{
if(elemcnt < 0 || elemsize <= 0 || c == nil)
return -1;
c->f = 0;
c->n = 0;
c->freed = 0;
memset(c, 0, sizeof *c);
c->e = elemsize;
c->s = elemcnt;
_threaddebug(DBGCHAN, "chaninit %p", c);
@ -104,13 +102,16 @@ alt(Alt *alts)
* chanlock. Instead, we delay the note until we've dropped
* the lock.
*/
/*
* T might be nil here -- the scheduler sends on threadwaitchan
* directly (in non-blocking mode, of course!).
*/
t = _threadgetproc()->thread;
if(t->moribund || _threadexitsallstatus)
if((t && t->moribund) || _threadexitsallstatus)
yield(); /* won't return */
s = _procsplhi();
lock(&chanlock);
t->alt = alts;
t->chan = Chanalt;
/* test whether any channels can proceed */
n = 0;
@ -125,7 +126,6 @@ alt(Alt *alts)
if(c==nil){
unlock(&chanlock);
_procsplx(s);
t->chan = Channone;
return -1;
}
if(canexec(xa))
@ -138,7 +138,6 @@ alt(Alt *alts)
if(xa->op == CHANNOBLK){
unlock(&chanlock);
_procsplx(s);
t->chan = Channone;
_threadnalt++;
return xa - alts;
}
@ -159,6 +158,9 @@ _threadnalt++;
* we need to be here.
*/
Again:
t->alt = alts;
t->chan = Chanalt;
unlock(&chanlock);
_procsplx(s);
r = _threadrendezvous((ulong)&c, 0);

View File

@ -86,6 +86,7 @@ proccreate(void (*f)(void*), void *arg, uint stacksize)
p = _threadgetproc();
if(p->idle){
fprint(2, "cannot create procs once there is an idle thread\n");
werrstr("cannot create procs once there is an idle thread");
return -1;
}
@ -124,6 +125,7 @@ threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize)
int id;
if(_threadprocs!=1){
fprint(2, "cannot have idle thread in multi-proc program\n");
werrstr("cannot have idle thread in multi-proc program");
return -1;
}
@ -153,6 +155,8 @@ _newproc(void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp, i
else
*_threadpq.tail = p;
_threadpq.tail = &p->next;
if(_threadprocs == 1)
_threadmultiproc();
_threadprocs++;
unlock(&_threadpq.lock);
return p;

View File

@ -2,28 +2,18 @@
#include <unistd.h>
#include "threadimpl.h"
static void efork(int[3], int[2], char*, char**);
void
procexec(Channel *pidc, int fd[3], char *prog, char *args[])
threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
{
int n;
Proc *p;
Thread *t;
_threaddebug(DBGEXEC, "procexec %s", prog);
/* must be only thread in proc */
p = _threadgetproc();
t = p->thread;
if(p->threads.head != t || p->threads.head->nextt != nil){
werrstr("not only thread in proc");
Bad:
_threaddebug(DBGEXEC, "procexec bad %r");
if(pidc)
sendul(pidc, ~0);
return;
}
int pfd[2];
int n, pid;
char exitstr[ERRMAX];
_threaddebug(DBGEXEC, "threadexec %s", prog);
/*
* We want procexec to behave like exec; if exec succeeds,
* We want threadexec to behave like exec; if exec succeeds,
* never return, and if it fails, return with errstr set.
* Unfortunately, the exec happens in another proc since
* we have to wait for the exec'ed process to finish.
@ -34,114 +24,77 @@ procexec(Channel *pidc, int fd[3], char *prog, char *args[])
* then the proc doing the exec sends the errstr down the
* pipe to us.
*/
if(pipe(p->exec.fd) < 0)
if(pipe(pfd) < 0)
goto Bad;
if(fcntl(p->exec.fd[0], F_SETFD, 1) < 0)
if(fcntl(pfd[0], F_SETFD, 1) < 0)
goto Bad;
if(fcntl(p->exec.fd[1], F_SETFD, 1) < 0)
if(fcntl(pfd[1], F_SETFD, 1) < 0)
goto Bad;
/* exec in parallel via the scheduler */
assert(p->needexec==0);
p->exec.prog = prog;
p->exec.args = args;
p->exec.stdfd = fd;
p->needexec = 1;
_sched();
switch(pid = fork()){
case -1:
close(pfd[0]);
close(pfd[1]);
goto Bad;
case 0:
efork(fd, pfd, prog, args);
_exit(0);
default:
break;
}
close(p->exec.fd[1]);
if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){ /* exec failed */
p->exitstr[n] = '\0';
errstr(p->exitstr, ERRMAX);
close(p->exec.fd[0]);
close(pfd[1]);
if((n = read(pfd[0], exitstr, ERRMAX-1)) > 0){ /* exec failed */
exitstr[n] = '\0';
errstr(exitstr, ERRMAX);
close(pfd[0]);
goto Bad;
}
close(p->exec.fd[0]);
close(pfd[0]);
close(fd[0]);
if(fd[1] != fd[0])
close(fd[1]);
if(fd[2] != fd[1] && fd[2] != fd[0])
close(fd[2]);
if(pidc)
sendul(pidc, t->ret);
sendul(pidc, pid);
_threaddebug(DBGEXEC, "procexec schedexecwait");
/* wait for exec'ed program, then exit */
_schedexecwait();
_threaddebug(DBGEXEC, "threadexec schedexecwait");
threadexits(0);
Bad:
_threaddebug(DBGEXEC, "threadexec bad %r");
if(pidc)
sendul(pidc, ~0);
}
void
procexecl(Channel *pidc, int fd[3], char *f, ...)
threadexecl(Channel *pidc, int fd[3], char *f, ...)
{
procexec(pidc, fd, f, &f+1);
}
void
_schedexecwait(void)
{
int pid;
Channel *c;
Proc *p;
Thread *t;
Waitmsg *w;
p = _threadgetproc();
t = p->thread;
pid = t->ret;
_threaddebug(DBGEXEC, "_schedexecwait %d", t->ret);
for(;;){
w = wait();
if(w == nil)
break;
if(w->pid == pid)
break;
free(w);
}
if(w != nil){
if((c = _threadwaitchan) != nil)
sendp(c, w);
else
free(w);
}
threadexits("procexec");
threadexec(pidc, fd, f, &f+1);
}
static void
efork(void *ve)
efork(int stdfd[3], int fd[2], char *prog, char **args)
{
char buf[ERRMAX];
Execargs *e;
int i;
e = ve;
_threaddebug(DBGEXEC, "_schedexec %s -- calling execv", e->prog);
dup(e->stdfd[0], 0);
dup(e->stdfd[1], 1);
dup(e->stdfd[2], 2);
_threaddebug(DBGEXEC, "_schedexec %s -- calling execv", prog);
dup(stdfd[0], 0);
dup(stdfd[1], 1);
dup(stdfd[2], 2);
for(i=3; i<40; i++)
if(i != e->fd[1])
if(i != fd[1])
close(i);
rfork(RFNOTEG);
execvp(e->prog, e->args);
execvp(prog, args);
_threaddebug(DBGEXEC, "_schedexec failed: %r");
rerrstr(buf, sizeof buf);
if(buf[0]=='\0')
strcpy(buf, "exec failed");
write(e->fd[1], buf, strlen(buf));
close(e->fd[1]);
write(fd[1], buf, strlen(buf));
close(fd[1]);
_exits(buf);
}
int
_schedexec(Execargs *e)
{
int pid;
pid = fork();
if(pid == 0){
efork(e);
_exit(1);
}
return pid;
}

View File

@ -24,6 +24,12 @@ _threaddie(int x)
exit(_threadexitsallstatus[0] ? 1 : 0);
}
static void
_nop(int x)
{
USED(x);
}
int
main(int argc, char **argv)
{
@ -31,6 +37,7 @@ main(int argc, char **argv)
Proc *p;
signal(SIGTERM, _threaddie);
signal(SIGCHLD, _nop);
// rfork(RFREND);
//_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0;

View File

@ -12,6 +12,7 @@ OFILES=\
debug.$O\
exec-unix.$O\
exit.$O\
fdwait.$O\
getpid.$O\
id.$O\
iocall.$O\
@ -30,6 +31,7 @@ OFILES=\
memsetd.$O\
note.$O\
proctab.$O\
read9pmsg.$O\
ref.$O\
rendez.$O\
sched.$O\

View File

@ -6,6 +6,18 @@ enum
PTABHASH = 257,
};
static int multi;
static Proc *theproc;
void
_threadmultiproc(void)
{
if(multi == 0){
multi = 1;
_threadsetproc(theproc);
}
}
static Lock ptablock;
Proc *ptab[PTABHASH];
@ -14,6 +26,10 @@ _threadsetproc(Proc *p)
{
int h;
if(!multi){
theproc = p;
return;
}
lock(&ptablock);
h = ((unsigned)p->pid)%PTABHASH;
p->link = ptab[h];
@ -27,6 +43,9 @@ __threadgetproc(int rm)
Proc **l, *p;
int h, pid;
if(!multi)
return theproc;
pid = _threadgetpid();
lock(&ptablock);

View File

@ -1,4 +1,5 @@
#include <signal.h>
#include <errno.h>
#include "threadimpl.h"
//static Thread *runthread(Proc*);
@ -67,10 +68,12 @@ _schedinit(void *arg)
t = nil;
_sched();
}
/*
if(p->needexec){
t->ret = _schedexec(&p->exec);
p->needexec = 0;
}
*/
if(p->newproc){
t->ret = _schedfork(p->newproc);
if(t->ret < 0){
@ -90,14 +93,45 @@ _schedinit(void *arg)
static Thread*
runthread(Proc *p)
{
Channel *c;
Thread *t;
Tqueue *q;
Waitmsg *w;
int e, sent;
if(p->nthreads==0 || (p->nthreads==1 && p->idle))
return nil;
q = &p->ready;
relock:
lock(&p->readylock);
if(q->head == nil){
e = errno;
if((c = _threadwaitchan) != nil){
if(c->n <= c->s){
sent = 0;
for(;;){
if((w = p->waitmsg) != nil)
p->waitmsg = nil;
else
w = waitnohang();
if(w == nil)
break;
if(sent == 0){
unlock(&p->readylock);
sent = 1;
}
if(nbsendp(c, w) != 1)
break;
}
p->waitmsg = w;
if(sent)
goto relock;
}
}else{
while((w = waitnohang()) != nil)
free(w);
}
errno = e;
if(p->idle){
if(p->idle->state != Ready){
fprint(2, "everyone is asleep\n");

View File

@ -139,6 +139,7 @@ struct Proc
void *arg; /* passed between shared and unshared stk */
char str[ERRMAX]; /* used by threadexits to avoid malloc */
char errbuf[ERRMAX]; /* errstr */
Waitmsg *waitmsg;
void* udata; /* User per-proc data pointer */
};
@ -181,6 +182,7 @@ void __threaddebug(ulong, char*, ...);
void _threadexitsall(char*);
void _threadflagrendez(Thread*);
Proc* _threadgetproc(void);
extern void _threadmultiproc(void);
Proc* _threaddelproc(void);
void _threadsetproc(Proc*);
void _threadinitstack(Thread*, void(*)(void*), void*);
@ -195,7 +197,6 @@ long _xdec(long*);
void _xinc(long*);
void _threadremove(Proc*, Thread*);
extern int _threadmultiproc;
extern int _threaddebuglevel;
extern char* _threadexitsallstatus;
extern Pqueue _threadpq;

View File

@ -1,13 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 1998-2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/

View File

@ -1,13 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 1998-2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/

View File

@ -1,13 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 1998-2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/

View File

@ -1,17 +0,0 @@
#include <string.h>
#include "utf.h"
#define nil ((void*)0)
#define uchar _fmtuchar
#define ushort _fmtushort
#define uint _fmtuint
#define ulong _fmtulong
#define vlong _fmtvlong
#define uvlong _fmtuvlong
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

View File

@ -1,31 +0,0 @@
PLAN9=../..
<$PLAN9/src/mkhdr
LIB=libutf.a
OFILES=\
rune.$O\
runestrcat.$O\
runestrchr.$O\
runestrcmp.$O\
runestrcpy.$O\
runestrdup.$O\
runestrlen.$O\
runestrecpy.$O\
runestrncat.$O\
runestrncmp.$O\
runestrncpy.$O\
runestrrchr.$O\
runestrstr.$O\
runetype.$O\
utfecpy.$O\
utflen.$O\
utfnlen.$O\
utfrrune.$O\
utfrune.$O\
utfutf.$O\
HFILES=\
$PLAN9/include/utf.h\
<$PLAN9/src/mksyslib

View File

@ -1,177 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
enum
{
Bit1 = 7,
Bitx = 6,
Bit2 = 5,
Bit3 = 4,
Bit4 = 3,
T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
Maskx = (1<<Bitx)-1, /* 0011 1111 */
Testx = Maskx ^ 0xFF, /* 1100 0000 */
Bad = Runeerror,
};
int
chartorune(Rune *rune, char *str)
{
int c, c1, c2;
long l;
/*
* one character sequence
* 00000-0007F => T1
*/
c = *(uchar*)str;
if(c < Tx) {
*rune = c;
return 1;
}
/*
* two character sequence
* 0080-07FF => T2 Tx
*/
c1 = *(uchar*)(str+1) ^ Tx;
if(c1 & Testx)
goto bad;
if(c < T3) {
if(c < T2)
goto bad;
l = ((c << Bitx) | c1) & Rune2;
if(l <= Rune1)
goto bad;
*rune = l;
return 2;
}
/*
* three character sequence
* 0800-FFFF => T3 Tx Tx
*/
c2 = *(uchar*)(str+2) ^ Tx;
if(c2 & Testx)
goto bad;
if(c < T4) {
l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
if(l <= Rune2)
goto bad;
*rune = l;
return 3;
}
/*
* bad decoding
*/
bad:
*rune = Bad;
return 1;
}
int
runetochar(char *str, Rune *rune)
{
long c;
/*
* one character sequence
* 00000-0007F => 00-7F
*/
c = *rune;
if(c <= Rune1) {
str[0] = c;
return 1;
}
/*
* two character sequence
* 0080-07FF => T2 Tx
*/
if(c <= Rune2) {
str[0] = T2 | (c >> 1*Bitx);
str[1] = Tx | (c & Maskx);
return 2;
}
/*
* three character sequence
* 0800-FFFF => T3 Tx Tx
*/
str[0] = T3 | (c >> 2*Bitx);
str[1] = Tx | ((c >> 1*Bitx) & Maskx);
str[2] = Tx | (c & Maskx);
return 3;
}
int
runelen(long c)
{
Rune rune;
char str[10];
rune = c;
return runetochar(str, &rune);
}
int
runenlen(Rune *r, int nrune)
{
int nb, c;
nb = 0;
while(nrune--) {
c = *r++;
if(c <= Rune1)
nb++;
else
if(c <= Rune2)
nb += 2;
else
nb += 3;
}
return nb;
}
int
fullrune(char *str, int n)
{
int c;
if(n > 0) {
c = *(uchar*)str;
if(c < Tx)
return 1;
if(n > 1)
if(c < T3 || n > 2)
return 1;
}
return 0;
}

View File

@ -1,25 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrcat(Rune *s1, Rune *s2)
{
runestrcpy(runestrchr(s1, 0), s2);
return s1;
}

View File

@ -1,35 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrchr(Rune *s, Rune c)
{
Rune c0 = c;
Rune c1;
if(c == 0) {
while(*s++)
;
return s-1;
}
while(c1 = *s++)
if(c1 == c0)
return s-1;
return 0;
}

View File

@ -1,35 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
int
runestrcmp(Rune *s1, Rune *s2)
{
Rune c1, c2;
for(;;) {
c1 = *s1++;
c2 = *s2++;
if(c1 != c2) {
if(c1 > c2)
return 1;
return -1;
}
if(c1 == 0)
return 0;
}
}

View File

@ -1,28 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrcpy(Rune *s1, Rune *s2)
{
Rune *os1;
os1 = s1;
while(*s1++ = *s2++)
;
return os1;
}

View File

@ -1,30 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrdup(Rune *s)
{
Rune *ns;
ns = malloc(sizeof(Rune)*(runestrlen(s) + 1));
if(ns == 0)
return 0;
return runestrcpy(ns, s);
}

View File

@ -1,32 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrecpy(Rune *s1, Rune *es1, Rune *s2)
{
if(s1 >= es1)
return s1;
while(*s1++ = *s2++){
if(s1 == es1){
*--s1 = '\0';
break;
}
}
return s1;
}

View File

@ -1,24 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
long
runestrlen(Rune *s)
{
return runestrchr(s, 0) - s;
}

View File

@ -1,32 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrncat(Rune *s1, Rune *s2, long n)
{
Rune *os1;
os1 = s1;
s1 = runestrchr(s1, 0);
while(*s1++ = *s2++)
if(--n < 0) {
s1[-1] = 0;
break;
}
return os1;
}

View File

@ -1,37 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
int
runestrncmp(Rune *s1, Rune *s2, long n)
{
Rune c1, c2;
while(n > 0) {
c1 = *s1++;
c2 = *s2++;
n--;
if(c1 != c2) {
if(c1 > c2)
return 1;
return -1;
}
if(c1 == 0)
break;
}
return 0;
}

View File

@ -1,33 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrncpy(Rune *s1, Rune *s2, long n)
{
int i;
Rune *os1;
os1 = s1;
for(i = 0; i < n; i++)
if((*s1++ = *s2++) == 0) {
while(++i < n)
*s1++ = 0;
return os1;
}
return os1;
}

View File

@ -1,30 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
Rune*
runestrrchr(Rune *s, Rune c)
{
Rune *r;
if(c == 0)
return runestrchr(s, 0);
r = 0;
while(s = runestrchr(s, c))
r = s++;
return r;
}

View File

@ -1,44 +0,0 @@
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <stdarg.h>
#include <string.h>
#include "utf.h"
#include "utfdef.h"
/*
* Return pointer to first occurrence of s2 in s1,
* 0 if none
*/
Rune*
runestrstr(Rune *s1, Rune *s2)
{
Rune *p, *pa, *pb;
int c0, c;
c0 = *s2;
if(c0 == 0)
return s1;
s2++;
for(p=runestrchr(s1, c0); p; p=runestrchr(p+1, c0)) {
pa = p;
for(pb=s2;; pb++) {
c = *pb;
if(c == 0)
return p;
if(c != *++pa)
break;
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
#define uchar _utfuchar
#define ushort _utfushort
#define uint _utfuint
#define ulong _utfulong
#define vlong _utfvlong
#define uvlong _utfuvlong
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
#define nil ((void*)0)

Some files were not shown because too many files have changed in this diff Show More