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