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