xref: /plan9-contrib/sys/src/ape/lib/ap/stdio/rdline.c (revision 22df390c30710ddd2119f3e7bb6c92dc399cabb9)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * pANS stdio -- rdline
33e12c5d1SDavid du Colombier  * This is not a pANS routine.
43e12c5d1SDavid du Colombier  */
53e12c5d1SDavid du Colombier #include "iolib.h"
63e12c5d1SDavid du Colombier #include <string.h>
73e12c5d1SDavid du Colombier 
rdline(FILE * f,char ** aep)8*22df390cSDavid du Colombier char *rdline(FILE *f, char **aep){
93e12c5d1SDavid du Colombier 	int cnt;
10*22df390cSDavid du Colombier 	void *vp;
11*22df390cSDavid du Colombier 	unsigned char *nlp;
12*22df390cSDavid du Colombier 	unsigned char **ep;
13*22df390cSDavid du Colombier 
14*22df390cSDavid du Colombier 	ep = (unsigned char **)aep;
153e12c5d1SDavid du Colombier 	switch(f->state){
163e12c5d1SDavid du Colombier 	default:	/* CLOSED, WR, ERR, EOF */
173e12c5d1SDavid du Colombier 		return NULL;
183e12c5d1SDavid du Colombier 	case OPEN:
193e12c5d1SDavid du Colombier 		_IO_setvbuf(f);
203e12c5d1SDavid du Colombier 	case RDWR:
213e12c5d1SDavid du Colombier 		f->state=RD;
223e12c5d1SDavid du Colombier 	case RD:
233e12c5d1SDavid du Colombier 		if(f->bufl==0){		/* Called by a comedian! */
243e12c5d1SDavid du Colombier 			f->state=ERR;
253e12c5d1SDavid du Colombier 			return NULL;
263e12c5d1SDavid du Colombier 		}
273e12c5d1SDavid du Colombier 		vp=f->rp;
283e12c5d1SDavid du Colombier 		for(;;){
293e12c5d1SDavid du Colombier 			/*
303e12c5d1SDavid du Colombier 			 * Look for a newline.
313e12c5d1SDavid du Colombier 			 * If none found, slide the partial line to the beginning
323e12c5d1SDavid du Colombier 			 * of the buffer, read some more and keep looking.
333e12c5d1SDavid du Colombier 			 */
343e12c5d1SDavid du Colombier 			nlp=memchr(f->rp, '\n', f->wp-f->rp);
353e12c5d1SDavid du Colombier 			if(nlp!=0) break;
363e12c5d1SDavid du Colombier 			if(f->flags&STRING){
373e12c5d1SDavid du Colombier 				f->rp=f->wp;
383e12c5d1SDavid du Colombier 				if(ep) *ep=f->wp;
393e12c5d1SDavid du Colombier 				return vp;
403e12c5d1SDavid du Colombier 			}
413e12c5d1SDavid du Colombier 			if(f->rp!=f->buf){
423e12c5d1SDavid du Colombier 				memmove(f->buf, f->rp, f->wp-f->rp);
433e12c5d1SDavid du Colombier 				f->wp-=f->rp-f->buf;
443e12c5d1SDavid du Colombier 				f->rp=f->buf;
453e12c5d1SDavid du Colombier 				vp=f->rp;
463e12c5d1SDavid du Colombier 			}
473e12c5d1SDavid du Colombier 			cnt=f->bufl-(f->wp-f->buf);
483e12c5d1SDavid du Colombier 			if(cnt==0){	/* no room left */
493e12c5d1SDavid du Colombier 				nlp=f->wp-1;
503e12c5d1SDavid du Colombier 				break;
513e12c5d1SDavid du Colombier 			}
523e12c5d1SDavid du Colombier 			cnt=read(f->fd, f->wp, cnt);
533e12c5d1SDavid du Colombier 			if(cnt==-1){
543e12c5d1SDavid du Colombier 				f->state=ERR;
553e12c5d1SDavid du Colombier 				return NULL;
563e12c5d1SDavid du Colombier 			}
573e12c5d1SDavid du Colombier 			if(cnt==0){	/* is this ok? */
583e12c5d1SDavid du Colombier 				f->state=EOF;
593e12c5d1SDavid du Colombier 				return NULL;
603e12c5d1SDavid du Colombier 			}
613e12c5d1SDavid du Colombier 			f->rp=f->wp;
623e12c5d1SDavid du Colombier 			f->wp+=cnt;
633e12c5d1SDavid du Colombier 		}
643e12c5d1SDavid du Colombier 		*nlp='\0';
653e12c5d1SDavid du Colombier 		f->rp=nlp+1;
663e12c5d1SDavid du Colombier 		if(ep) *ep=nlp;
673e12c5d1SDavid du Colombier 		return vp;
683e12c5d1SDavid du Colombier 	}
693e12c5d1SDavid du Colombier }
70