diff options
| -rw-r--r-- | include/bio.h | 30 | ||||
| -rw-r--r-- | libbio/bgetc.c | 1 | ||||
| -rw-r--r-- | libbio/bgetrune.c | 16 | ||||
| -rw-r--r-- | libbio/binit.c | 20 | ||||
| -rw-r--r-- | libbio/boffset.c | 4 | ||||
| -rw-r--r-- | libbio/bprint.c | 23 | ||||
| -rw-r--r-- | libbio/bputc.c | 29 | ||||
| -rw-r--r-- | libbio/bputrune.c | 2 | ||||
| -rw-r--r-- | libbio/brdstr.c | 111 | ||||
| -rw-r--r-- | libbio/bseek.c | 21 | ||||
| -rw-r--r-- | libbio/bvprint.c | 36 | ||||
| -rw-r--r-- | libbio/bwrite.c | 6 | ||||
| -rw-r--r-- | libbio/mkfile | 2 |
13 files changed, 217 insertions, 84 deletions
diff --git a/include/bio.h b/include/bio.h index b4e552d8..67ec18ed 100644 --- a/include/bio.h +++ b/include/bio.h @@ -5,7 +5,7 @@ typedef struct Biobuf Biobuf; enum { Bsize = 8*1024, - Bungetsize = 4, /* space for ungetc */ + Bungetsize = UTFmax+1, /* space for ungetc */ Bmagic = 0x314159, Beof = -1, Bbad = -2, @@ -27,7 +27,7 @@ struct Biobuf int state; /* r/w/inactive */ int fid; /* open file */ int flag; /* magic if malloc'ed */ - long offset; /* offset of buffer in file */ + vlong offset; /* offset of buffer in file */ int bsize; /* size of buffer */ uchar* bbuf; /* pointer to beginning of buffer */ uchar* ebuf; /* pointer to end of buffer */ @@ -35,20 +35,12 @@ struct Biobuf uchar b[Bungetsize+Bsize]; }; -#define BGETC(bp)\ - ((bp)->icount?(bp)->bbuf[(bp)->bsize+(bp)->icount++]:Bgetc((bp))) -#define BPUTC(bp,c)\ - ((bp)->ocount?(bp)->bbuf[(bp)->bsize+(bp)->ocount++]=(c),0:Bputc((bp),(c))) -#define BOFFSET(bp)\ - (((bp)->state==Bractive)?\ - (bp)->offset + (bp)->icount:\ - (((bp)->state==Bwactive)?\ - (bp)->offset + ((bp)->bsize + (bp)->ocount):\ - -1)) -#define BLINELEN(bp)\ - (bp)->rdline -#define BFILDES(bp)\ - (bp)->fid +/* Dregs, redefined as functions for backwards compatibility */ +#define BGETC(bp) Bgetc(bp) +#define BPUTC(bp,c) Bputc(bp,c) +#define BOFFSET(bp) Boffset(bp) +#define BLINELEN(bp) Blinelen(bp) +#define BFILDES(bp) Bfildes(bp) int Bbuffered(Biobuf*); int Bfildes(Biobuf*); @@ -59,14 +51,16 @@ long Bgetrune(Biobuf*); int Binit(Biobuf*, int, int); int Binits(Biobuf*, int, int, uchar*, int); int Blinelen(Biobuf*); -long Boffset(Biobuf*); +vlong Boffset(Biobuf*); Biobuf* Bopen(char*, int); int Bprint(Biobuf*, char*, ...); +int Bvprint(Biobuf*, char*, va_list); int Bputc(Biobuf*, int); int Bputrune(Biobuf*, long); void* Brdline(Biobuf*, int); +char* Brdstr(Biobuf*, int, int); long Bread(Biobuf*, void*, long); -long Bseek(Biobuf*, long, int); +vlong Bseek(Biobuf*, vlong, int); int Bterm(Biobuf*); int Bungetc(Biobuf*); int Bungetrune(Biobuf*); diff --git a/libbio/bgetc.c b/libbio/bgetc.c index 4c8ae90c..741b692f 100644 --- a/libbio/bgetc.c +++ b/libbio/bgetc.c @@ -26,6 +26,7 @@ loop: i = read(bp->fid, bp->bbuf, bp->bsize); bp->gbuf = bp->bbuf; if(i <= 0) { + bp->state = Bracteof; if(i < 0) bp->state = Binactive; return Beof; diff --git a/libbio/bgetrune.c b/libbio/bgetrune.c index ed216379..13b02bec 100644 --- a/libbio/bgetrune.c +++ b/libbio/bgetrune.c @@ -6,7 +6,7 @@ Bgetrune(Biobuf *bp) { int c, i; Rune rune; - char str[4]; + char str[UTFmax]; c = Bgetc(bp); if(c < Runeself) { /* one char */ @@ -14,19 +14,25 @@ Bgetrune(Biobuf *bp) return c; } str[0] = c; + bp->runesize = 0; for(i=1;;) { c = Bgetc(bp); if(c < 0) return c; + if (i >= sizeof str) + return Runeerror; str[i++] = c; if(fullrune(str, i)) { + /* utf is long enough to be a rune, but could be bad. */ bp->runesize = chartorune(&rune, str); - while(i > bp->runesize) { - Bungetc(bp); - i--; - } + if (rune == Runeerror) + bp->runesize = 0; /* push back nothing */ + else + /* push back bytes unconsumed by chartorune */ + for(; i > bp->runesize; i--) + Bungetc(bp); return rune; } } diff --git a/libbio/binit.c b/libbio/binit.c index ecbad119..4d9bc785 100644 --- a/libbio/binit.c +++ b/libbio/binit.c @@ -61,7 +61,7 @@ Binits(Biobuf *bp, int f, int mode, uchar *p, int size) p += Bungetsize; /* make room for Bungets */ size -= Bungetsize; - switch(mode) { + switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) { default: fprint(2, "Bopen: unknown mode %d\n", mode); return Beof; @@ -103,22 +103,21 @@ Bopen(char *name, int mode) Biobuf *bp; int f; - switch(mode) { + switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) { default: fprint(2, "Bopen: unknown mode %d\n", mode); return 0; case OREAD: f = open(name, OREAD); - if(f < 0) - return 0; break; case OWRITE: - f = create(name, OWRITE, 0666); - if(f < 0) - return 0; + f = create(name, mode, 0666); + break; } + if(f < 0) + return 0; bp = malloc(sizeof(Biobuf)); if(bp == nil) return 0; @@ -130,13 +129,16 @@ Bopen(char *name, int mode) int Bterm(Biobuf *bp) { + int r; deinstall(bp); - Bflush(bp); + r = Bflush(bp); if(bp->flag == Bmagic) { bp->flag = 0; close(bp->fid); + bp->fid = -1; /* prevent accidents */ free(bp); } - return 0; + /* otherwise opened with Binit(s) */ + return r; } diff --git a/libbio/boffset.c b/libbio/boffset.c index 72ce34cf..88c4c358 100644 --- a/libbio/boffset.c +++ b/libbio/boffset.c @@ -1,10 +1,10 @@ #include "lib9.h" #include <bio.h> -long +vlong Boffset(Biobuf *bp) { - long n; + vlong n; switch(bp->state) { default: diff --git a/libbio/bprint.c b/libbio/bprint.c index 26870024..36890e6d 100644 --- a/libbio/bprint.c +++ b/libbio/bprint.c @@ -4,26 +4,11 @@ int Bprint(Biobuf *bp, char *fmt, ...) { - va_list ap; - char *ip, *ep, *out; + va_list arg; int n; - ep = (char*)bp->ebuf; - ip = ep + bp->ocount; - va_start(ap, fmt); - out = vseprint(ip, ep, fmt, ap); - va_end(ap); - if(out == nil || out >= ep-5) { - if(Bflush(bp) < 0) - return Beof; - ip = ep + bp->ocount; - va_start(ap, fmt); - out = vseprint(ip, ep, fmt, ap); - va_end(ap); - if(out == nil || out >= ep-5) - return Beof; - } - n = out-ip; - bp->ocount += n; + va_start(arg, fmt); + n = Bvprint(bp, fmt, arg); + va_end(arg); return n; } diff --git a/libbio/bputc.c b/libbio/bputc.c index 5f0fba59..d05badaa 100644 --- a/libbio/bputc.c +++ b/libbio/bputc.c @@ -4,26 +4,17 @@ int Bputc(Biobuf *bp, int c) { - int i, j; + int i; -loop: - i = bp->ocount; - j = i+1; - if(i != 0) { - bp->ocount = j; - bp->ebuf[i] = c; - return 0; + for(;;) { + i = bp->ocount; + if(i) { + bp->ebuf[i++] = c; + bp->ocount = i; + return 0; + } + if(Bflush(bp) == Beof) + break; } - if(bp->state != Bwactive) - return Beof; - j = write(bp->fid, bp->bbuf, bp->bsize); - if(j == bp->bsize) { - bp->ocount = -bp->bsize; - bp->offset += j; - goto loop; - } - fprint(2, "Bputc: write error\n"); - bp->state = Binactive; - bp->ocount = 0; return Beof; } diff --git a/libbio/bputrune.c b/libbio/bputrune.c index a864541d..4b4a7a9a 100644 --- a/libbio/bputrune.c +++ b/libbio/bputrune.c @@ -5,7 +5,7 @@ int Bputrune(Biobuf *bp, long c) { Rune rune; - char str[4]; + char str[UTFmax]; int n; rune = c; diff --git a/libbio/brdstr.c b/libbio/brdstr.c new file mode 100644 index 00000000..227bdd62 --- /dev/null +++ b/libbio/brdstr.c @@ -0,0 +1,111 @@ +#include "lib9.h" +#include <bio.h> + +static char* +badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim) +{ + int n; + + n = *np; + p = realloc(p, n+ndata+1); + if(p){ + memmove(p+n, data, ndata); + n += ndata; + if(n>0 && nulldelim && p[n-1]==delim) + p[--n] = '\0'; + else + p[n] = '\0'; + *np = n; + } + return p; +} + +char* +Brdstr(Biobuf *bp, int delim, int nulldelim) +{ + char *ip, *ep, *p; + int i, j; + + i = -bp->icount; + bp->rdline = 0; + if(i == 0) { + /* + * eof or other error + */ + if(bp->state != Bractive) { + if(bp->state == Bracteof) + bp->state = Bractive; + bp->gbuf = bp->ebuf; + return nil; + } + } + + /* + * first try in remainder of buffer (gbuf doesn't change) + */ + ip = (char*)bp->ebuf - i; + ep = memchr(ip, delim, i); + if(ep) { + j = (ep - ip) + 1; + bp->icount += j; + return badd(nil, &bp->rdline, ip, j, delim, nulldelim); + } + + /* + * copy data to beginning of buffer + */ + if(i < bp->bsize) + memmove(bp->bbuf, ip, i); + bp->gbuf = bp->bbuf; + + /* + * append to buffer looking for the delim + */ + p = nil; + for(;;){ + ip = (char*)bp->bbuf + i; + while(i < bp->bsize) { + j = read(bp->fid, ip, bp->bsize-i); + if(j <= 0 && i == 0) + return p; + if(j <= 0 && i > 0){ + /* + * end of file but no delim. pretend we got a delim + * by making the delim \0 and smashing it with nulldelim. + */ + j = 1; + ep = ip; + delim = '\0'; + nulldelim = 1; + *ep = delim; /* there will be room for this */ + }else{ + bp->offset += j; + ep = memchr(ip, delim, j); + } + i += j; + if(ep) { + /* + * found in new piece + * copy back up and reset everything + */ + ip = (char*)bp->ebuf - i; + if(i < bp->bsize){ + memmove(ip, bp->bbuf, i); + bp->gbuf = (uchar*)ip; + } + j = (ep - (char*)bp->bbuf) + 1; + bp->icount = j - i; + return badd(p, &bp->rdline, ip, j, delim, nulldelim); + } + ip += j; + } + + /* + * full buffer without finding; add to user string and continue + */ + p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0); + i = 0; + bp->icount = 0; + bp->gbuf = bp->ebuf; + } +} diff --git a/libbio/bseek.c b/libbio/bseek.c index 9e68f5ea..32e8dda4 100644 --- a/libbio/bseek.c +++ b/libbio/bseek.c @@ -1,10 +1,10 @@ #include "lib9.h" #include <bio.h> -long -Bseek(Biobuf *bp, long offset, int base) +vlong +Bseek(Biobuf *bp, vlong offset, int base) { - long n, d; + vlong n, d; switch(bp->state) { default: @@ -27,15 +27,16 @@ Bseek(Biobuf *bp, long offset, int base) * try to seek within buffer */ if(base == 0) { + /* + * if d is too large for an int, icount may wrap, + * so we need to ensure that icount hasn't wrapped + * and points within the buffer's valid data. + */ d = n - Boffset(bp); bp->icount += d; - if(d >= 0) { - if(bp->icount <= 0) - return n; - } else { - if(bp->ebuf - bp->gbuf >= -bp->icount) - return n; - } + if(d <= bp->bsize && bp->icount <= 0 && + bp->ebuf - bp->gbuf >= -bp->icount) + return n; } /* diff --git a/libbio/bvprint.c b/libbio/bvprint.c new file mode 100644 index 00000000..c11b1dc3 --- /dev/null +++ b/libbio/bvprint.c @@ -0,0 +1,36 @@ +#include "lib9.h" +#include <bio.h> + +static int +fmtBflush(Fmt *f) +{ + Biobuf *bp; + + bp = f->farg; + bp->ocount = (char*)f->to - (char*)f->stop; + if(Bflush(bp) < 0) + return 0; + f->stop = bp->ebuf; + f->to = (char*)f->stop + bp->ocount; + f->start = f->to; + return 1; +} + +int +Bvprint(Biobuf *bp, char *fmt, va_list arg) +{ + int n; + Fmt f; + + f.runes = 0; + f.stop = bp->ebuf; + f.start = (char*)f.stop + bp->ocount; + f.to = f.start; + f.flush = fmtBflush; + f.farg = bp; + f.nfmt = 0; + f.args = arg; + n = dofmt(&f, fmt); + bp->ocount = (char*)f.to - (char*)f.stop; + return n; +} diff --git a/libbio/bwrite.c b/libbio/bwrite.c index 87256fd0..7661b745 100644 --- a/libbio/bwrite.c +++ b/libbio/bwrite.c @@ -7,6 +7,7 @@ Bwrite(Biobuf *bp, void *ap, long count) long c; uchar *p; int i, n, oc; + char errbuf[ERRMAX]; p = ap; c = count; @@ -21,7 +22,10 @@ Bwrite(Biobuf *bp, void *ap, long count) return Beof; i = write(bp->fid, bp->bbuf, bp->bsize); if(i != bp->bsize) { - bp->state = Binactive; + errstr(errbuf, sizeof errbuf); + if(strstr(errbuf, "interrupt") == nil) + bp->state = Binactive; + errstr(errbuf, sizeof errbuf); return Beof; } bp->offset += i; diff --git a/libbio/mkfile b/libbio/mkfile index e9afe025..d3f60869 100644 --- a/libbio/mkfile +++ b/libbio/mkfile @@ -14,8 +14,10 @@ OFILES=\ bputrune.$O\ bputc.$O\ brdline.$O\ + brdstr.$O\ bread.$O\ bseek.$O\ + bvprint.$O\ bwrite.$O\ HFILES= $ROOT/include/bio.h |
