/***********************************************************************1* *2* This software is part of the ast package *3* Copyright (c) 1985-2011 AT&T Intellectual Property *4* and is licensed under the *5* Eclipse Public License, Version 1.0 *6* by AT&T Intellectual Property *7* *8* A copy of the License is available at *9* http://www.eclipse.org/org/documents/epl-v10.html *10* (with md5 checksum b35adb5213ca9657e911e9befb180842) *11* *12* Information and Software Systems Research *13* AT&T Research *14* Florham Park NJ *15* *16* Glenn Fowler <[email protected]> *17* David Korn <[email protected]> *18* Phong Vo <[email protected]> *19* *20***********************************************************************/21#include "sfhdr.h"2223/* Read a record delineated by a character.24** The record length can be accessed via sfvalue(f).25**26** Written by Kiem-Phong Vo27*/2829#if __STD_C30char* sfgetr(Sfio_t *f, int rc, int type)31#else32char* sfgetr(f,rc,type)33Sfio_t* f; /* stream to read from */34int rc; /* record separator */35int type;36#endif37{38ssize_t n, un;39uchar *s, *ends, *us;40int found;41Sfrsrv_t* rsrv;42SFMTXDECL(f); /* declare a local stream variable for multithreading */4344SFMTXENTER(f, NIL(char*));4546if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) )47SFMTXRETURN(f, NIL(char*));48SFLOCK(f,0);4950/* buffer to be returned */51rsrv = NIL(Sfrsrv_t*);52us = NIL(uchar*);53un = 0;54found = 0;5556/* compatibility mode */57type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type;5859if(type&SF_LASTR) /* return the broken record */60{ if((f->flags&SF_STRING) && (un = f->endb - f->next))61{ us = f->next;62f->next = f->endb;63found = 1;64}65else if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0)66{ us = rsrv->data;67found = 1;68}69goto done;70}7172while(!found)73{ /* fill buffer if necessary */74if((n = (ends = f->endb) - (s = f->next)) <= 0)75{ /* for unseekable devices, peek-read 1 record */76f->getr = rc;77f->mode |= SF_RC;7879/* fill buffer the conventional way */80if(SFRPEEK(f,s,n) <= 0)81{ us = NIL(uchar*);82goto done;83}84else85{ ends = s+n;86if(f->mode&SF_RC)87{ s = ends[-1] == rc ? ends-1 : ends;88goto do_copy;89}90}91}9293#if _lib_memchr94if(!(s = (uchar*)memchr((char*)s,rc,n)))95s = ends;96#else97while(*s != rc)98if((s += 1) == ends)99break;100#endif101do_copy:102if(s < ends) /* found separator */103{ s += 1; /* include the separator */104found = 1;105106if(!us &&107(!(type&SF_STRING) || !(f->flags&SF_STRING) ||108((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) )109{ /* returning data in buffer */110us = f->next;111un = s - f->next;112f->next = s;113goto done;114}115}116117/* amount to be read */118n = s - f->next;119120if(!found && (_Sfmaxr > 0 && un+n+1 >= _Sfmaxr || (f->flags&SF_STRING))) /* already exceed limit */121{ us = NIL(uchar*);122goto done;123}124125/* get internal buffer */126if(!rsrv || rsrv->size < un+n+1)127{ if(rsrv)128rsrv->slen = un;129if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*))130us = rsrv->data;131else132{ us = NIL(uchar*);133goto done;134}135}136137/* now copy data */138s = us+un;139un += n;140ends = f->next;141f->next += n;142MEMCPY(s,ends,n);143}144145done:146_Sfi = f->val = un;147f->getr = 0;148if(found && rc != 0 && (type&SF_STRING) )149{ us[un-1] = '\0';150if(us >= f->data && us < f->endb)151{ f->getr = rc;152f->mode |= SF_GETR;153}154}155156/* prepare for a call to get the broken record */157if(rsrv)158rsrv->slen = found ? 0 : -un;159160SFOPEN(f,0);161162if(us && (type&SF_LOCKR) )163{ f->mode |= SF_PEEK|SF_GETR;164f->endr = f->data;165}166167SFMTXRETURN(f, (char*)us);168}169170171