xref: /plan9/sys/src/ape/lib/ap/stdio/rdline.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier /*
2*3e12c5d1SDavid du Colombier  * pANS stdio -- rdline
3*3e12c5d1SDavid du Colombier  * This is not a pANS routine.
4*3e12c5d1SDavid du Colombier  */
5*3e12c5d1SDavid du Colombier #include "iolib.h"
6*3e12c5d1SDavid du Colombier #include <string.h>
7*3e12c5d1SDavid du Colombier 
rdline(FILE * f,char ** ep)8*3e12c5d1SDavid du Colombier char *rdline(FILE *f, char **ep){
9*3e12c5d1SDavid du Colombier 	int cnt;
10*3e12c5d1SDavid du Colombier 	char *nlp, *vp;
11*3e12c5d1SDavid du Colombier 	switch(f->state){
12*3e12c5d1SDavid du Colombier 	default:	/* CLOSED, WR, ERR, EOF */
13*3e12c5d1SDavid du Colombier 		return NULL;
14*3e12c5d1SDavid du Colombier 	case OPEN:
15*3e12c5d1SDavid du Colombier 		_IO_setvbuf(f);
16*3e12c5d1SDavid du Colombier 	case RDWR:
17*3e12c5d1SDavid du Colombier 		f->state=RD;
18*3e12c5d1SDavid du Colombier 	case RD:
19*3e12c5d1SDavid du Colombier 		if(f->bufl==0){		/* Called by a comedian! */
20*3e12c5d1SDavid du Colombier 			f->state=ERR;
21*3e12c5d1SDavid du Colombier 			return NULL;
22*3e12c5d1SDavid du Colombier 		}
23*3e12c5d1SDavid du Colombier 		vp=f->rp;
24*3e12c5d1SDavid du Colombier 		for(;;){
25*3e12c5d1SDavid du Colombier 			/*
26*3e12c5d1SDavid du Colombier 			 * Look for a newline.
27*3e12c5d1SDavid du Colombier 			 * If none found, slide the partial line to the beginning
28*3e12c5d1SDavid du Colombier 			 * of the buffer, read some more and keep looking.
29*3e12c5d1SDavid du Colombier 			 */
30*3e12c5d1SDavid du Colombier 			nlp=memchr(f->rp, '\n', f->wp-f->rp);
31*3e12c5d1SDavid du Colombier 			if(nlp!=0) break;
32*3e12c5d1SDavid du Colombier 			if(f->flags&STRING){
33*3e12c5d1SDavid du Colombier 				f->rp=f->wp;
34*3e12c5d1SDavid du Colombier 				if(ep) *ep=f->wp;
35*3e12c5d1SDavid du Colombier 				return vp;
36*3e12c5d1SDavid du Colombier 			}
37*3e12c5d1SDavid du Colombier 			if(f->rp!=f->buf){
38*3e12c5d1SDavid du Colombier 				memmove(f->buf, f->rp, f->wp-f->rp);
39*3e12c5d1SDavid du Colombier 				f->wp-=f->rp-f->buf;
40*3e12c5d1SDavid du Colombier 				f->rp=f->buf;
41*3e12c5d1SDavid du Colombier 				vp=f->rp;
42*3e12c5d1SDavid du Colombier 			}
43*3e12c5d1SDavid du Colombier 			cnt=f->bufl-(f->wp-f->buf);
44*3e12c5d1SDavid du Colombier 			if(cnt==0){	/* no room left */
45*3e12c5d1SDavid du Colombier 				nlp=f->wp-1;
46*3e12c5d1SDavid du Colombier 				break;
47*3e12c5d1SDavid du Colombier 			}
48*3e12c5d1SDavid du Colombier 			cnt=read(f->fd, f->wp, cnt);
49*3e12c5d1SDavid du Colombier 			if(cnt==-1){
50*3e12c5d1SDavid du Colombier 				f->state=ERR;
51*3e12c5d1SDavid du Colombier 				return NULL;
52*3e12c5d1SDavid du Colombier 			}
53*3e12c5d1SDavid du Colombier 			if(cnt==0){	/* is this ok? */
54*3e12c5d1SDavid du Colombier 				f->state=EOF;
55*3e12c5d1SDavid du Colombier 				return NULL;
56*3e12c5d1SDavid du Colombier 			}
57*3e12c5d1SDavid du Colombier 			f->rp=f->wp;
58*3e12c5d1SDavid du Colombier 			f->wp+=cnt;
59*3e12c5d1SDavid du Colombier 		}
60*3e12c5d1SDavid du Colombier 		*nlp='\0';
61*3e12c5d1SDavid du Colombier 		f->rp=nlp+1;
62*3e12c5d1SDavid du Colombier 		if(ep) *ep=nlp;
63*3e12c5d1SDavid du Colombier 		return vp;
64*3e12c5d1SDavid du Colombier 	}
65*3e12c5d1SDavid du Colombier }
66