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:
parent
d51419bf43
commit
5a8e63b2f0
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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*) */
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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++){
|
||||
|
||||
@ -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*
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "../libfmt/nan.h"
|
||||
#include "fmt/nan.h"
|
||||
|
||||
double
|
||||
NaN(void)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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>.
|
||||
|
||||
@ -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>.
|
||||
|
||||
@ -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>.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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 */
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
221
src/libfmt/fmt.c
221
src/libfmt/fmt.c
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
extern double __NaN(void);
|
||||
extern double __Inf(int);
|
||||
extern int __isNaN(double);
|
||||
extern int __isInf(double, int);
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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 .
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
extern double __NaN(void);
|
||||
extern double __Inf(int);
|
||||
extern double __isNaN(double);
|
||||
extern double __isInf(double, int);
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -5,6 +5,7 @@ LIB=libplumb.a
|
||||
OFILES=\
|
||||
event.$O\
|
||||
mesg.$O\
|
||||
thread.$O\
|
||||
|
||||
HFILES=$PLAN9/include/plumb.h
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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\
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
@ -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.
|
||||
*/
|
||||
@ -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.
|
||||
*/
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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
@ -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
Loading…
Reference in New Issue
Block a user