summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/stdio/rdline.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/stdio/rdline.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/stdio/rdline.c')
-rwxr-xr-xsys/src/ape/lib/ap/stdio/rdline.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/stdio/rdline.c b/sys/src/ape/lib/ap/stdio/rdline.c
new file mode 100755
index 000000000..6281a97e8
--- /dev/null
+++ b/sys/src/ape/lib/ap/stdio/rdline.c
@@ -0,0 +1,65 @@
+/*
+ * pANS stdio -- rdline
+ * This is not a pANS routine.
+ */
+#include "iolib.h"
+#include <string.h>
+
+char *rdline(FILE *f, char **ep){
+ int cnt;
+ char *nlp, *vp;
+ switch(f->state){
+ default: /* CLOSED, WR, ERR, EOF */
+ return NULL;
+ case OPEN:
+ _IO_setvbuf(f);
+ case RDWR:
+ f->state=RD;
+ case RD:
+ if(f->bufl==0){ /* Called by a comedian! */
+ f->state=ERR;
+ return NULL;
+ }
+ vp=f->rp;
+ for(;;){
+ /*
+ * Look for a newline.
+ * If none found, slide the partial line to the beginning
+ * of the buffer, read some more and keep looking.
+ */
+ nlp=memchr(f->rp, '\n', f->wp-f->rp);
+ if(nlp!=0) break;
+ if(f->flags&STRING){
+ f->rp=f->wp;
+ if(ep) *ep=f->wp;
+ return vp;
+ }
+ if(f->rp!=f->buf){
+ memmove(f->buf, f->rp, f->wp-f->rp);
+ f->wp-=f->rp-f->buf;
+ f->rp=f->buf;
+ vp=f->rp;
+ }
+ cnt=f->bufl-(f->wp-f->buf);
+ if(cnt==0){ /* no room left */
+ nlp=f->wp-1;
+ break;
+ }
+ cnt=read(f->fd, f->wp, cnt);
+ if(cnt==-1){
+ f->state=ERR;
+ return NULL;
+ }
+ if(cnt==0){ /* is this ok? */
+ f->state=EOF;
+ return NULL;
+ }
+ f->rp=f->wp;
+ f->wp+=cnt;
+ }
+ *nlp='\0';
+ f->rp=nlp+1;
+ if(ep) *ep=nlp;
+ return vp;
+ }
+}