|  | #include	"lib9.h" | 
|  | #include	<bio.h> | 
|  |  | 
|  | static char* | 
|  | badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim) | 
|  | { | 
|  | int n; | 
|  |  | 
|  | n = *np; | 
|  | p = realloc(p, n+ndata+1); | 
|  | if(p){ | 
|  | memmove(p+n, data, ndata); | 
|  | n += ndata; | 
|  | if(n>0 && nulldelim && p[n-1]==delim) | 
|  | p[--n] = '\0'; | 
|  | else | 
|  | p[n] = '\0'; | 
|  | *np = n; | 
|  | } | 
|  | return p; | 
|  | } | 
|  |  | 
|  | char* | 
|  | Brdstr(Biobuf *bp, int delim, int nulldelim) | 
|  | { | 
|  | char *ip, *ep, *p; | 
|  | int i, j; | 
|  |  | 
|  | i = -bp->icount; | 
|  | bp->rdline = 0; | 
|  | if(i == 0) { | 
|  | /* | 
|  | * eof or other error | 
|  | */ | 
|  | if(bp->state != Bractive) { | 
|  | if(bp->state == Bracteof) | 
|  | bp->state = Bractive; | 
|  | bp->gbuf = bp->ebuf; | 
|  | return nil; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * first try in remainder of buffer (gbuf doesn't change) | 
|  | */ | 
|  | ip = (char*)bp->ebuf - i; | 
|  | ep = memchr(ip, delim, i); | 
|  | if(ep) { | 
|  | j = (ep - ip) + 1; | 
|  | bp->icount += j; | 
|  | return badd(nil, &bp->rdline, ip, j, delim, nulldelim); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * copy data to beginning of buffer | 
|  | */ | 
|  | if(i < bp->bsize) | 
|  | memmove(bp->bbuf, ip, i); | 
|  | bp->gbuf = bp->bbuf; | 
|  |  | 
|  | /* | 
|  | * append to buffer looking for the delim | 
|  | */ | 
|  | p = nil; | 
|  | for(;;){ | 
|  | ip = (char*)bp->bbuf + i; | 
|  | while(i < bp->bsize) { | 
|  | j = read(bp->fid, ip, bp->bsize-i); | 
|  | if(j <= 0 && i == 0) | 
|  | return p; | 
|  | if(j <= 0 && i > 0){ | 
|  | /* | 
|  | * end of file but no delim. pretend we got a delim | 
|  | * by making the delim \0 and smashing it with nulldelim. | 
|  | */ | 
|  | j = 1; | 
|  | ep = ip; | 
|  | delim = '\0'; | 
|  | nulldelim = 1; | 
|  | *ep = delim;	/* there will be room for this */ | 
|  | }else{ | 
|  | bp->offset += j; | 
|  | ep = memchr(ip, delim, j); | 
|  | } | 
|  | i += j; | 
|  | if(ep) { | 
|  | /* | 
|  | * found in new piece | 
|  | * copy back up and reset everything | 
|  | */ | 
|  | ip = (char*)bp->ebuf - i; | 
|  | if(i < bp->bsize){ | 
|  | memmove(ip, bp->bbuf, i); | 
|  | bp->gbuf = (unsigned char*)ip; | 
|  | } | 
|  | j = (ep - (char*)bp->bbuf) + 1; | 
|  | bp->icount = j - i; | 
|  | return badd(p, &bp->rdline, ip, j, delim, nulldelim); | 
|  | } | 
|  | ip += j; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * full buffer without finding; add to user string and continue | 
|  | */ | 
|  | p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0); | 
|  | i = 0; | 
|  | bp->icount = 0; | 
|  | bp->gbuf = bp->ebuf; | 
|  | } | 
|  | } |