14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #include "sfdchdr.h"
234887Schin
244887Schin /* Discipline to turn \r\n into \n.
254887Schin ** This is useful to deal with DOS text files.
264887Schin **
274887Schin ** Written by David Korn (03/18/1998).
284887Schin */
294887Schin
304887Schin #define MINMAP 8
314887Schin #define CHUNK 1024
324887Schin
334887Schin struct map
344887Schin {
354887Schin Sfoff_t logical;
364887Schin Sfoff_t physical;
374887Schin };
384887Schin
394887Schin typedef struct _dosdisc
404887Schin {
414887Schin Sfdisc_t disc;
424887Schin struct map *maptable;
434887Schin int mapsize;
444887Schin int maptop;
454887Schin Sfoff_t lhere;
464887Schin Sfoff_t llast;
474887Schin Sfoff_t lmax;
484887Schin Sfoff_t pmax;
494887Schin Sfoff_t phere;
504887Schin Sfoff_t plast;
514887Schin Sfoff_t begin;
524887Schin int skip;
534887Schin void *buff;
544887Schin char last;
554887Schin char extra;
564887Schin int bsize;
574887Schin } Dosdisc_t;
584887Schin
594887Schin #if __STD_C
addmapping(register Dosdisc_t * dp)604887Schin static void addmapping(register Dosdisc_t *dp)
614887Schin #else
624887Schin static void addmapping(dp)
634887Schin register Dosdisc_t *dp;
644887Schin #endif
654887Schin {
664887Schin register int n;
674887Schin if((n=dp->maptop++)>=dp->mapsize)
684887Schin {
694887Schin dp->mapsize *= 2;
704887Schin if(!(dp->maptable=(struct map*)realloc((void*)dp->maptable,(dp->mapsize+1)*sizeof(struct map))))
714887Schin {
724887Schin dp->maptop--;
734887Schin dp->mapsize *= 2;
744887Schin return;
754887Schin }
764887Schin }
774887Schin dp->maptable[n].physical = dp->phere;
784887Schin dp->maptable[n].logical = dp->lhere;
794887Schin dp->maptable[dp->maptop].logical=0;
804887Schin }
814887Schin
824887Schin #if __STD_C
getmapping(Dosdisc_t * dp,Sfoff_t offset,register int whence)834887Schin static struct map *getmapping(Dosdisc_t *dp, Sfoff_t offset, register int whence)
844887Schin #else
854887Schin static struct map *getmapping(dp, offset, whence)
864887Schin Dosdisc_t *dp;
874887Schin Sfoff_t offset;
884887Schin register int whence;
894887Schin #endif
904887Schin {
914887Schin register struct map *mp;
924887Schin static struct map dummy;
934887Schin if(offset <= dp->begin)
944887Schin {
954887Schin dummy.logical = dummy.physical = offset;
964887Schin return(&dummy);
974887Schin }
984887Schin if(!(mp=dp->maptable))
994887Schin {
1004887Schin dummy.logical = dp->begin;
1014887Schin dummy.physical = dummy.logical+1;
1024887Schin return(&dummy);
1034887Schin }
1044887Schin while((++mp)->logical && (whence==SEEK_CUR?mp->physical:mp->logical) <= offset);
1054887Schin return(mp-1);
1064887Schin }
1074887Schin
1084887Schin #if __STD_C
dos_read(Sfio_t * iop,void * buff,size_t size,Sfdisc_t * disc)1094887Schin static ssize_t dos_read(Sfio_t *iop, void *buff, size_t size, Sfdisc_t* disc)
1104887Schin #else
1114887Schin static ssize_t dos_read(iop, buff, size, disc)
1124887Schin Sfio_t *iop;
1134887Schin void *buff;
1144887Schin size_t size;
1154887Schin Sfdisc_t* disc;
1164887Schin #endif
1174887Schin {
1184887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc;
1194887Schin register char *cp = (char*)buff, *first, *cpmax;
1204887Schin register int n, count, m;
1214887Schin if(dp->extra)
1224887Schin {
1234887Schin dp->extra=0;
1244887Schin *cp = dp->last;
1254887Schin return(1);
1264887Schin }
1274887Schin while(1)
1284887Schin {
1294887Schin if((n = sfrd(iop,buff,size,disc)) <= 0)
1304887Schin return(n);
1314887Schin dp->plast=dp->phere;
1324887Schin dp->phere +=n;
1334887Schin dp->llast = dp->lhere;
1344887Schin cpmax = cp+n-1;
1354887Schin if(dp->last=='\r' && *cp!='\n')
1364887Schin {
1374887Schin /* should insert a '\r' */ ;
1384887Schin }
1394887Schin dp->last = *cpmax;
1404887Schin if(n>1)
1414887Schin break;
1424887Schin if(dp->last!='\r')
1434887Schin {
1444887Schin dp->lhere++;
1454887Schin return(1);
1464887Schin }
1474887Schin }
1484887Schin if(dp->last=='\r')
1494887Schin n--;
1504887Schin else if(dp->last!='\n' || cpmax[-1]!='\r')
1514887Schin *cpmax = '\r';
1524887Schin dp->lhere += n;
1534887Schin while(1)
1544887Schin {
1554887Schin while(*cp++ != '\r');
1564887Schin if(cp > cpmax || *cp=='\n')
1574887Schin break;
1584887Schin }
1594887Schin dp->skip = cp-1 - (char*)buff;
1604887Schin /* if not \r\n in buffer, just return */
1614887Schin if((count = cpmax+1-cp) <=0)
1624887Schin {
1634887Schin *cpmax = dp->last;
1644887Schin if(!dp->maptable)
1654887Schin dp->begin +=n;
1664887Schin dp->skip++;
1674887Schin count=0;
1684887Schin goto done;
1694887Schin }
1704887Schin if(!dp->maptable)
1714887Schin {
1724887Schin dp->begin += cp - (char*)buff-1;
1734887Schin if(dp->maptable=(struct map*)malloc((MINMAP+1)*sizeof(struct map)))
1744887Schin {
1754887Schin dp->mapsize = MINMAP;
1764887Schin dp->maptable[0].logical= dp->begin;
1774887Schin dp->maptable[0].physical = dp->maptable[0].logical+1;
1784887Schin dp->maptable[1].logical=0;
1794887Schin dp->maptop = 1;
1804887Schin }
1814887Schin }
1824887Schin /* save original discipline inside buffer */
1834887Schin if(count>dp->bsize)
1844887Schin {
1854887Schin if(dp->bsize==0)
1864887Schin dp->buff = malloc(count);
1874887Schin else
1884887Schin dp->buff = realloc(dp->buff,count);
1894887Schin dp->bsize = count;
1904887Schin if(!dp->buff)
1914887Schin return(-1);
1924887Schin }
1934887Schin memcpy(dp->buff, cp, count);
1944887Schin count=1;
1954887Schin while(1)
1964887Schin {
1974887Schin first=cp;
1984887Schin if(cp==cpmax)
1994887Schin cp++;
2004887Schin else
2014887Schin while(*cp++ != '\r');
2024887Schin if(cp<=cpmax && *cp!='\n')
2034887Schin continue;
2044887Schin if((m=(cp-first)-1) >0)
2054887Schin memcpy(first-count, first, m);
2064887Schin if(cp > cpmax)
2074887Schin break;
2084887Schin count++;
2094887Schin }
2104887Schin cpmax[-count] = dp->last;
2114887Schin dp->lhere -= count;
2124887Schin done:
2134887Schin if(dp->lhere>dp->lmax)
2144887Schin {
2154887Schin dp->lmax = dp->lhere;
2164887Schin dp->pmax = dp->phere;
2174887Schin if(dp->maptable && dp->lmax > dp->maptable[dp->maptop-1].logical+CHUNK)
2184887Schin addmapping(dp);
2194887Schin }
2204887Schin return(n-count);
2214887Schin }
2224887Schin
2234887Schin /*
2244887Schin * returns the current offset
2254887Schin * <offset> must be in the current buffer
2264887Schin * if <whence> is SEEK_CUR, physical offset converted to logical offset
2274887Schin * otherwise, logical offset is converted to physical offset
2284887Schin */
2294887Schin #if __STD_C
cur_offset(Dosdisc_t * dp,Sfoff_t offset,Sfio_t * iop,register int whence)2304887Schin static Sfoff_t cur_offset(Dosdisc_t *dp, Sfoff_t offset,Sfio_t *iop,register int whence)
2314887Schin #else
2324887Schin static Sfoff_t cur_offset(dp, offset, iop, whence)
2334887Schin Dosdisc_t *dp;
2344887Schin Sfoff_t offset;
2354887Schin Sfio_t *iop;
2364887Schin register int whence;
2374887Schin #endif
2384887Schin {
2394887Schin register Sfoff_t n,m=0;
2404887Schin register char *cp;
2414887Schin
2424887Schin if(whence==SEEK_CUR)
2434887Schin {
2444887Schin whence= -1;
2454887Schin n = offset - dp->plast;
2464887Schin iop->next = iop->data + n;
2474887Schin offset = dp->llast;
2484887Schin }
2494887Schin else
2504887Schin {
2514887Schin whence = 1;
2524887Schin n = offset - dp->llast;
2534887Schin offset = dp->plast;
2544887Schin }
2554887Schin offset +=n;
2564887Schin if((n -= dp->skip) > 0)
2574887Schin {
2584887Schin m=whence;
2594887Schin cp = (char*)dp->buff;
2604887Schin while(n--)
2614887Schin {
2624887Schin if(*cp++=='\r' && *cp=='\n')
2634887Schin {
2644887Schin m += whence;
2654887Schin if(whence>0)
2664887Schin n++;
2674887Schin }
2684887Schin }
2694887Schin }
2704887Schin if(whence<0)
2714887Schin iop->next += m;
2724887Schin return(offset+m);
2734887Schin }
2744887Schin
2754887Schin #if __STD_C
dos_seek(Sfio_t * iop,Sfoff_t offset,register int whence,Sfdisc_t * disc)2764887Schin static Sfoff_t dos_seek(Sfio_t *iop, Sfoff_t offset, register int whence, Sfdisc_t* disc)
2774887Schin #else
2784887Schin static Sfoff_t dos_seek(iop, offset, whence, disc)
2794887Schin Sfio_t *iop;
2804887Schin Sfoff_t offset;
2814887Schin register int whence;
2824887Schin Sfdisc_t* disc;
2834887Schin #endif
2844887Schin {
2854887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc;
2864887Schin struct map dummy, *mp=0;
2874887Schin Sfoff_t physical;
2884887Schin register int n,size;
2894887Schin retry:
2904887Schin switch(whence)
2914887Schin {
2924887Schin case SEEK_CUR:
2934887Schin offset = sfsk(iop, (Sfoff_t)0,SEEK_CUR,disc);
2944887Schin if(offset<=dp->begin)
2954887Schin return(offset);
2964887Schin /* check for seek outside buffer */
2974887Schin if(offset==dp->phere)
2984887Schin return(dp->lhere);
2994887Schin else if(offset==dp->plast)
3004887Schin return(dp->llast);
3014887Schin else if(offset<dp->plast || offset>dp->phere)
3024887Schin mp = getmapping(dp,offset,whence);
3034887Schin break;
3044887Schin case SEEK_SET:
3054887Schin /* check for seek outside buffer */
3064887Schin if(offset<dp->llast || offset > dp->lhere)
3074887Schin mp = getmapping(dp,offset,whence);
3084887Schin break;
3094887Schin case SEEK_END:
3104887Schin if(!dp->maptable)
3114887Schin return(sfsk(iop,offset,SEEK_END,disc));
3124887Schin mp = &dummy;
3134887Schin mp->physical = dp->plast;
3144887Schin mp->logical = dp->llast;
3154887Schin break;
3164887Schin }
3174887Schin if(sfsetbuf(iop,(char*)iop,0))
3184887Schin size = sfvalue(iop);
3194887Schin else
3204887Schin size = iop->endb-iop->data;
3214887Schin if(mp)
3224887Schin {
3234887Schin sfsk(iop,mp->physical,SEEK_SET,disc);
3244887Schin dp->phere = mp->physical;
3254887Schin dp->lhere = mp->logical;
3264887Schin if((*disc->readf)(iop,iop->data,size,disc)<0)
3274887Schin return(-1);
3284887Schin }
3294887Schin while(1)
3304887Schin {
3314887Schin if(whence==SEEK_CUR && dp->phere>=offset)
3324887Schin break;
3334887Schin if(whence==SEEK_SET && dp->lhere>=offset)
3344887Schin break;
3354887Schin n=(*disc->readf)(iop,iop->data,size,disc);
3364887Schin if(n < 0)
3374887Schin return(-1);
3384887Schin if(n==0)
3394887Schin {
3404887Schin if(whence==SEEK_END && offset<0)
3414887Schin {
3424887Schin offset = dp->lhere;
3434887Schin whence=SEEK_SET;
3444887Schin goto retry;
3454887Schin }
3464887Schin break;
3474887Schin }
3484887Schin }
3494887Schin if(whence==SEEK_END)
3504887Schin offset += dp->lhere;
3514887Schin else
3524887Schin {
3534887Schin physical = cur_offset(dp,offset,iop,whence);
3544887Schin if(whence==SEEK_SET)
3554887Schin {
3564887Schin sfsk(iop, physical ,SEEK_SET,disc);
3574887Schin dp->phere = physical;
3584887Schin dp->lhere = offset;
3594887Schin }
3604887Schin else
3614887Schin offset = physical;
3624887Schin }
3634887Schin return(offset);
3644887Schin }
3654887Schin
3664887Schin #if __STD_C
dos_except(Sfio_t * iop,int type,void * arg,Sfdisc_t * disc)3674887Schin static int dos_except(Sfio_t *iop, int type, void *arg, Sfdisc_t *disc)
3684887Schin #else
3694887Schin static int dos_except(iop, type, arg, disc)
3704887Schin Sfio_t *iop;
3714887Schin int type;
3724887Schin void *arg;
3734887Schin Sfdisc_t *disc;
3744887Schin #endif
3754887Schin {
3764887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc;
3774887Schin if(type==SF_DPOP || type==SF_FINAL)
3784887Schin {
3794887Schin if(dp->bsize>0)
3804887Schin free((void*)dp->buff);
3814887Schin if(dp->mapsize)
3824887Schin free((void*)dp->maptable);
3834887Schin free((void*)disc);
3844887Schin }
3854887Schin return(0);
3864887Schin }
3874887Schin
3884887Schin #if __STD_C
sfdcdos(Sfio_t * f)3894887Schin int sfdcdos(Sfio_t *f)
3904887Schin #else
3914887Schin int sfdcdos(f)
3924887Schin Sfio_t *f;
3934887Schin #endif
3944887Schin {
3954887Schin Dosdisc_t *dos;
3964887Schin
3974887Schin /* this is a readonly discipline */
3984887Schin if(sfset(f,0,0)&SF_WRITE)
3994887Schin return(-1);
4004887Schin
4014887Schin if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) )
4024887Schin return -1;
4034887Schin memset(dos,'\0',sizeof(Dosdisc_t));
4044887Schin
4054887Schin dos->disc.readf = dos_read;
4064887Schin dos->disc.writef = NIL(Sfwrite_f);
4074887Schin dos->disc.seekf = dos_seek;
4084887Schin dos->disc.exceptf = dos_except;
4094887Schin
4104887Schin if(sfdisc(f,(Sfdisc_t*)dos) != (Sfdisc_t*)dos)
4114887Schin { free(dos);
4124887Schin return -1;
4134887Schin }
4144887Schin
4154887Schin return(0);
4164887Schin }
417