1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #include	"sfdchdr.h"
23da2e3ebdSchin 
24da2e3ebdSchin /*	Discipline to turn \r\n into \n.
25da2e3ebdSchin **	This is useful to deal with DOS text files.
26da2e3ebdSchin **
27da2e3ebdSchin **	Written by David Korn (03/18/1998).
28da2e3ebdSchin */
29da2e3ebdSchin 
30da2e3ebdSchin #define MINMAP	8
31da2e3ebdSchin #define CHUNK	1024
32da2e3ebdSchin 
33da2e3ebdSchin struct map
34da2e3ebdSchin {
35da2e3ebdSchin 	Sfoff_t	logical;
36da2e3ebdSchin 	Sfoff_t	physical;
37da2e3ebdSchin };
38da2e3ebdSchin 
39da2e3ebdSchin typedef struct _dosdisc
40da2e3ebdSchin {
41da2e3ebdSchin 	Sfdisc_t	disc;
42da2e3ebdSchin 	struct map	*maptable;
43da2e3ebdSchin 	int		mapsize;
44da2e3ebdSchin 	int		maptop;
45da2e3ebdSchin 	Sfoff_t		lhere;
46da2e3ebdSchin 	Sfoff_t		llast;
47da2e3ebdSchin 	Sfoff_t		lmax;
48da2e3ebdSchin 	Sfoff_t		pmax;
49da2e3ebdSchin 	Sfoff_t		phere;
50da2e3ebdSchin 	Sfoff_t		plast;
51da2e3ebdSchin 	Sfoff_t		begin;
52da2e3ebdSchin 	int		skip;
53da2e3ebdSchin 	void		*buff;
54da2e3ebdSchin 	char		last;
55da2e3ebdSchin 	char		extra;
56da2e3ebdSchin 	int		bsize;
57da2e3ebdSchin } Dosdisc_t;
58da2e3ebdSchin 
59da2e3ebdSchin #if __STD_C
addmapping(register Dosdisc_t * dp)60da2e3ebdSchin static void addmapping(register Dosdisc_t *dp)
61da2e3ebdSchin #else
62da2e3ebdSchin static void addmapping(dp)
63da2e3ebdSchin register Dosdisc_t *dp;
64da2e3ebdSchin #endif
65da2e3ebdSchin {
66da2e3ebdSchin 	register int n;
67da2e3ebdSchin 	if((n=dp->maptop++)>=dp->mapsize)
68da2e3ebdSchin 	{
69da2e3ebdSchin 		dp->mapsize *= 2;
70da2e3ebdSchin 		if(!(dp->maptable=(struct map*)realloc((void*)dp->maptable,(dp->mapsize+1)*sizeof(struct map))))
71da2e3ebdSchin 		{
72da2e3ebdSchin 			dp->maptop--;
73da2e3ebdSchin 			dp->mapsize *= 2;
74da2e3ebdSchin 			return;
75da2e3ebdSchin 		}
76da2e3ebdSchin 	}
77da2e3ebdSchin 	dp->maptable[n].physical = dp->phere;
78da2e3ebdSchin 	dp->maptable[n].logical = dp->lhere;
79da2e3ebdSchin 	dp->maptable[dp->maptop].logical=0;
80da2e3ebdSchin }
81da2e3ebdSchin 
82da2e3ebdSchin #if __STD_C
getmapping(Dosdisc_t * dp,Sfoff_t offset,register int whence)83da2e3ebdSchin static struct map *getmapping(Dosdisc_t *dp, Sfoff_t offset, register int whence)
84da2e3ebdSchin #else
85da2e3ebdSchin static struct map *getmapping(dp, offset, whence)
86da2e3ebdSchin Dosdisc_t *dp;
87da2e3ebdSchin Sfoff_t offset;
88da2e3ebdSchin register int whence;
89da2e3ebdSchin #endif
90da2e3ebdSchin {
91da2e3ebdSchin 	register struct map *mp;
92da2e3ebdSchin 	static struct map dummy;
93da2e3ebdSchin 	if(offset <= dp->begin)
94da2e3ebdSchin 	{
95da2e3ebdSchin 		dummy.logical = dummy.physical = offset;
96da2e3ebdSchin 		return(&dummy);
97da2e3ebdSchin 	}
98da2e3ebdSchin 	if(!(mp=dp->maptable))
99da2e3ebdSchin 	{
100da2e3ebdSchin 		dummy.logical = dp->begin;
101da2e3ebdSchin 		dummy.physical = dummy.logical+1;
102da2e3ebdSchin 		return(&dummy);
103da2e3ebdSchin 	}
104da2e3ebdSchin 	while((++mp)->logical && (whence==SEEK_CUR?mp->physical:mp->logical) <= offset);
105da2e3ebdSchin 	return(mp-1);
106da2e3ebdSchin }
107da2e3ebdSchin 
108da2e3ebdSchin #if __STD_C
dos_read(Sfio_t * iop,void * buff,size_t size,Sfdisc_t * disc)109da2e3ebdSchin static ssize_t dos_read(Sfio_t *iop, void *buff, size_t size, Sfdisc_t* disc)
110da2e3ebdSchin #else
111da2e3ebdSchin static ssize_t dos_read(iop, buff, size, disc)
112da2e3ebdSchin Sfio_t *iop;
113da2e3ebdSchin void *buff;
114da2e3ebdSchin size_t size;
115da2e3ebdSchin Sfdisc_t* disc;
116da2e3ebdSchin #endif
117da2e3ebdSchin {
118da2e3ebdSchin 	register Dosdisc_t *dp = (Dosdisc_t*)disc;
119da2e3ebdSchin 	register char *cp = (char*)buff, *first, *cpmax;
120da2e3ebdSchin 	register int n, count, m;
121da2e3ebdSchin 	if(dp->extra)
122da2e3ebdSchin 	{
123da2e3ebdSchin 		dp->extra=0;
124da2e3ebdSchin 		*cp = dp->last;
125da2e3ebdSchin 		return(1);
126da2e3ebdSchin 	}
127da2e3ebdSchin 	while(1)
128da2e3ebdSchin 	{
129da2e3ebdSchin 		if((n = sfrd(iop,buff,size,disc)) <= 0)
130da2e3ebdSchin 			return(n);
131da2e3ebdSchin 		dp->plast=dp->phere;
132da2e3ebdSchin 		dp->phere +=n;
133da2e3ebdSchin 		dp->llast = dp->lhere;
134da2e3ebdSchin 		cpmax = cp+n-1;
135da2e3ebdSchin 		if(dp->last=='\r' && *cp!='\n')
136da2e3ebdSchin 		{
137da2e3ebdSchin 			/* should insert a '\r' */ ;
138da2e3ebdSchin 		}
139da2e3ebdSchin 		dp->last = *cpmax;
140da2e3ebdSchin 		if(n>1)
141da2e3ebdSchin 			break;
142da2e3ebdSchin 		if(dp->last!='\r')
143da2e3ebdSchin 		{
144da2e3ebdSchin 			dp->lhere++;
145da2e3ebdSchin 			return(1);
146da2e3ebdSchin 		}
147da2e3ebdSchin 	}
148da2e3ebdSchin 	if(dp->last=='\r')
149da2e3ebdSchin 		n--;
150da2e3ebdSchin 	else if(dp->last!='\n' || cpmax[-1]!='\r')
151da2e3ebdSchin 		*cpmax = '\r';
152da2e3ebdSchin 	dp->lhere += n;
153da2e3ebdSchin 	while(1)
154da2e3ebdSchin 	{
155da2e3ebdSchin 		while(*cp++ != '\r');
156da2e3ebdSchin 		if(cp > cpmax || *cp=='\n')
157da2e3ebdSchin 			break;
158da2e3ebdSchin 	}
159da2e3ebdSchin 	dp->skip = cp-1 - (char*)buff;
160da2e3ebdSchin 	/* if not \r\n in buffer, just return */
161da2e3ebdSchin 	if((count = cpmax+1-cp) <=0)
162da2e3ebdSchin 	{
163da2e3ebdSchin 		*cpmax = dp->last;
164da2e3ebdSchin 		if(!dp->maptable)
165da2e3ebdSchin 			dp->begin +=n;
166da2e3ebdSchin 		dp->skip++;
167da2e3ebdSchin 		count=0;
168da2e3ebdSchin 		goto done;
169da2e3ebdSchin 	}
170da2e3ebdSchin 	if(!dp->maptable)
171da2e3ebdSchin 	{
172da2e3ebdSchin 		dp->begin += cp - (char*)buff-1;
173da2e3ebdSchin 		if(dp->maptable=(struct map*)malloc((MINMAP+1)*sizeof(struct map)))
174da2e3ebdSchin 		{
175da2e3ebdSchin 			dp->mapsize = MINMAP;
176da2e3ebdSchin 			dp->maptable[0].logical=  dp->begin;
177da2e3ebdSchin 			dp->maptable[0].physical = dp->maptable[0].logical+1;
178da2e3ebdSchin 			dp->maptable[1].logical=0;
179da2e3ebdSchin 			dp->maptop = 1;
180da2e3ebdSchin 		}
181da2e3ebdSchin 	}
182da2e3ebdSchin 	/* save original discipline inside buffer */
183da2e3ebdSchin 	if(count>dp->bsize)
184da2e3ebdSchin 	{
185da2e3ebdSchin 		if(dp->bsize==0)
186da2e3ebdSchin 			dp->buff = malloc(count);
187da2e3ebdSchin 		else
188da2e3ebdSchin 			dp->buff = realloc(dp->buff,count);
189da2e3ebdSchin 		dp->bsize = count;
190da2e3ebdSchin 		if(!dp->buff)
191da2e3ebdSchin 			return(-1);
192da2e3ebdSchin 	}
193da2e3ebdSchin 	memcpy(dp->buff, cp, count);
194da2e3ebdSchin 	count=1;
195da2e3ebdSchin 	while(1)
196da2e3ebdSchin 	{
197da2e3ebdSchin 		first=cp;
198da2e3ebdSchin 		if(cp==cpmax)
199da2e3ebdSchin 			cp++;
200da2e3ebdSchin 		else
201da2e3ebdSchin 			while(*cp++ != '\r');
202da2e3ebdSchin 		if(cp<=cpmax && *cp!='\n')
203da2e3ebdSchin 			continue;
204da2e3ebdSchin 		if((m=(cp-first)-1) >0)
205da2e3ebdSchin 			memcpy(first-count, first, m);
206da2e3ebdSchin 		if(cp > cpmax)
207da2e3ebdSchin 			break;
208da2e3ebdSchin 		count++;
209da2e3ebdSchin 	}
210da2e3ebdSchin 	cpmax[-count] = dp->last;
211da2e3ebdSchin 	dp->lhere -= count;
212da2e3ebdSchin done:
213da2e3ebdSchin 	if(dp->lhere>dp->lmax)
214da2e3ebdSchin 	{
215da2e3ebdSchin 		dp->lmax = dp->lhere;
216da2e3ebdSchin 		dp->pmax = dp->phere;
217da2e3ebdSchin 		if(dp->maptable && dp->lmax > dp->maptable[dp->maptop-1].logical+CHUNK)
218da2e3ebdSchin 			addmapping(dp);
219da2e3ebdSchin 	}
220da2e3ebdSchin 	return(n-count);
221da2e3ebdSchin }
222da2e3ebdSchin 
223da2e3ebdSchin /*
224da2e3ebdSchin  * returns the current offset
225da2e3ebdSchin  * <offset> must be in the current buffer
226da2e3ebdSchin  * if <whence> is SEEK_CUR, physical offset converted to logical offset
227da2e3ebdSchin  *  otherwise, logical offset is converted to physical offset
228da2e3ebdSchin  */
229da2e3ebdSchin #if __STD_C
cur_offset(Dosdisc_t * dp,Sfoff_t offset,Sfio_t * iop,register int whence)230da2e3ebdSchin static Sfoff_t cur_offset(Dosdisc_t *dp, Sfoff_t offset,Sfio_t *iop,register int whence)
231da2e3ebdSchin #else
232da2e3ebdSchin static Sfoff_t cur_offset(dp, offset, iop, whence)
233da2e3ebdSchin Dosdisc_t *dp;
234da2e3ebdSchin Sfoff_t offset;
235da2e3ebdSchin Sfio_t *iop;
236da2e3ebdSchin register int whence;
237da2e3ebdSchin #endif
238da2e3ebdSchin {
239da2e3ebdSchin 	register Sfoff_t n,m=0;
240da2e3ebdSchin 	register char *cp;
241da2e3ebdSchin 
242da2e3ebdSchin 	if(whence==SEEK_CUR)
243da2e3ebdSchin 	{
244da2e3ebdSchin 		whence= -1;
245da2e3ebdSchin 		n = offset - dp->plast;
246da2e3ebdSchin 		iop->next = iop->data + n;
247da2e3ebdSchin 		offset =  dp->llast;
248da2e3ebdSchin 	}
249da2e3ebdSchin 	else
250da2e3ebdSchin 	{
251da2e3ebdSchin 		whence = 1;
252da2e3ebdSchin 		n = offset - dp->llast;
253da2e3ebdSchin 		offset = dp->plast;
254da2e3ebdSchin 	}
255da2e3ebdSchin 	offset +=n;
256da2e3ebdSchin 	if((n -= dp->skip) > 0)
257da2e3ebdSchin 	{
258da2e3ebdSchin 		m=whence;
259da2e3ebdSchin 		cp = (char*)dp->buff;
260da2e3ebdSchin 		while(n--)
261da2e3ebdSchin 		{
262da2e3ebdSchin 			if(*cp++=='\r' && *cp=='\n')
263da2e3ebdSchin 			{
264da2e3ebdSchin 				m += whence;
265da2e3ebdSchin 				if(whence>0)
266da2e3ebdSchin 					n++;
267da2e3ebdSchin 			}
268da2e3ebdSchin 		}
269da2e3ebdSchin 	}
270da2e3ebdSchin 	if(whence<0)
271da2e3ebdSchin 		iop->next += m;
272da2e3ebdSchin 	return(offset+m);
273da2e3ebdSchin }
274da2e3ebdSchin 
275da2e3ebdSchin #if __STD_C
dos_seek(Sfio_t * iop,Sfoff_t offset,register int whence,Sfdisc_t * disc)276da2e3ebdSchin static Sfoff_t dos_seek(Sfio_t *iop, Sfoff_t offset, register int whence, Sfdisc_t* disc)
277da2e3ebdSchin #else
278da2e3ebdSchin static Sfoff_t dos_seek(iop, offset, whence, disc)
279da2e3ebdSchin Sfio_t *iop;
280da2e3ebdSchin Sfoff_t offset;
281da2e3ebdSchin register int whence;
282da2e3ebdSchin Sfdisc_t* disc;
283da2e3ebdSchin #endif
284da2e3ebdSchin {
285da2e3ebdSchin 	register Dosdisc_t *dp = (Dosdisc_t*)disc;
286da2e3ebdSchin 	struct map dummy, *mp=0;
287da2e3ebdSchin 	Sfoff_t physical;
288da2e3ebdSchin 	register int n,size;
289da2e3ebdSchin retry:
290da2e3ebdSchin 	switch(whence)
291da2e3ebdSchin 	{
292da2e3ebdSchin 	    case SEEK_CUR:
293da2e3ebdSchin 		offset = sfsk(iop, (Sfoff_t)0,SEEK_CUR,disc);
294da2e3ebdSchin 		if(offset<=dp->begin)
295da2e3ebdSchin 			return(offset);
296da2e3ebdSchin 		/* check for seek outside buffer */
297da2e3ebdSchin 		if(offset==dp->phere)
298da2e3ebdSchin 			return(dp->lhere);
299da2e3ebdSchin 		else if(offset==dp->plast)
300da2e3ebdSchin 			return(dp->llast);
301da2e3ebdSchin 		else if(offset<dp->plast || offset>dp->phere)
302da2e3ebdSchin 			mp = getmapping(dp,offset,whence);
303da2e3ebdSchin 		break;
304da2e3ebdSchin 	    case SEEK_SET:
305da2e3ebdSchin 		/* check for seek outside buffer */
306da2e3ebdSchin 		if(offset<dp->llast || offset > dp->lhere)
307da2e3ebdSchin 			mp = getmapping(dp,offset,whence);
308da2e3ebdSchin 		break;
309da2e3ebdSchin 	    case SEEK_END:
310da2e3ebdSchin 		if(!dp->maptable)
311da2e3ebdSchin 			return(sfsk(iop,offset,SEEK_END,disc));
312da2e3ebdSchin 		mp = &dummy;
313da2e3ebdSchin 		mp->physical = dp->plast;
314da2e3ebdSchin 		mp->logical = dp->llast;
315da2e3ebdSchin 		break;
316da2e3ebdSchin 	}
317da2e3ebdSchin 	if(sfsetbuf(iop,(char*)iop,0))
318da2e3ebdSchin 		size = sfvalue(iop);
319da2e3ebdSchin 	else
320da2e3ebdSchin 		size = iop->endb-iop->data;
321da2e3ebdSchin 	if(mp)
322da2e3ebdSchin 	{
323da2e3ebdSchin 		sfsk(iop,mp->physical,SEEK_SET,disc);
324da2e3ebdSchin 		dp->phere = mp->physical;
325da2e3ebdSchin 		dp->lhere = mp->logical;
326da2e3ebdSchin 		if((*disc->readf)(iop,iop->data,size,disc)<0)
327da2e3ebdSchin 			return(-1);
328da2e3ebdSchin 	}
329da2e3ebdSchin 	while(1)
330da2e3ebdSchin 	{
331da2e3ebdSchin 		if(whence==SEEK_CUR && dp->phere>=offset)
332da2e3ebdSchin 			break;
333da2e3ebdSchin 		if(whence==SEEK_SET && dp->lhere>=offset)
334da2e3ebdSchin 			break;
335da2e3ebdSchin 		n=(*disc->readf)(iop,iop->data,size,disc);
336da2e3ebdSchin 		if(n < 0)
337da2e3ebdSchin 			return(-1);
338da2e3ebdSchin 		if(n==0)
339da2e3ebdSchin 		{
340da2e3ebdSchin 			if(whence==SEEK_END && offset<0)
341da2e3ebdSchin 			{
342da2e3ebdSchin 				offset = dp->lhere;
343da2e3ebdSchin 				whence=SEEK_SET;
344da2e3ebdSchin 				goto retry;
345da2e3ebdSchin 			}
346da2e3ebdSchin 			break;
347da2e3ebdSchin 		}
348da2e3ebdSchin 	}
349da2e3ebdSchin 	if(whence==SEEK_END)
350da2e3ebdSchin 		offset += dp->lhere;
351da2e3ebdSchin 	else
352da2e3ebdSchin 	{
353da2e3ebdSchin 		physical = cur_offset(dp,offset,iop,whence);
354da2e3ebdSchin 		if(whence==SEEK_SET)
355da2e3ebdSchin 		{
356da2e3ebdSchin 			sfsk(iop, physical ,SEEK_SET,disc);
357da2e3ebdSchin 			dp->phere = physical;
358da2e3ebdSchin 			dp->lhere = offset;
359da2e3ebdSchin 		}
360da2e3ebdSchin 		else
361da2e3ebdSchin 			offset = physical;
362da2e3ebdSchin 	}
363da2e3ebdSchin 	return(offset);
364da2e3ebdSchin }
365da2e3ebdSchin 
366da2e3ebdSchin #if __STD_C
dos_except(Sfio_t * iop,int type,void * arg,Sfdisc_t * disc)367da2e3ebdSchin static int dos_except(Sfio_t *iop, int type, void *arg, Sfdisc_t *disc)
368da2e3ebdSchin #else
369da2e3ebdSchin static int dos_except(iop, type, arg, disc)
370da2e3ebdSchin Sfio_t *iop;
371da2e3ebdSchin int type;
372da2e3ebdSchin void *arg;
373da2e3ebdSchin Sfdisc_t *disc;
374da2e3ebdSchin #endif
375da2e3ebdSchin {
376da2e3ebdSchin 	register Dosdisc_t *dp = (Dosdisc_t*)disc;
377da2e3ebdSchin 	if(type==SF_DPOP || type==SF_FINAL)
378da2e3ebdSchin 	{
379da2e3ebdSchin 		if(dp->bsize>0)
380da2e3ebdSchin 			free((void*)dp->buff);
381da2e3ebdSchin 		if(dp->mapsize)
382da2e3ebdSchin 			free((void*)dp->maptable);
383da2e3ebdSchin 		free((void*)disc);
384da2e3ebdSchin 	}
385da2e3ebdSchin 	return(0);
386da2e3ebdSchin }
387da2e3ebdSchin 
388da2e3ebdSchin #if __STD_C
sfdcdos(Sfio_t * f)389da2e3ebdSchin int sfdcdos(Sfio_t *f)
390da2e3ebdSchin #else
391da2e3ebdSchin int sfdcdos(f)
392da2e3ebdSchin Sfio_t *f;
393da2e3ebdSchin #endif
394da2e3ebdSchin {
395da2e3ebdSchin 	Dosdisc_t *dos;
396da2e3ebdSchin 
397da2e3ebdSchin 	/* this is a readonly discipline */
398da2e3ebdSchin 	if(sfset(f,0,0)&SF_WRITE)
399da2e3ebdSchin 		return(-1);
400da2e3ebdSchin 
401da2e3ebdSchin 	if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) )
402da2e3ebdSchin 		return -1;
403da2e3ebdSchin 	memset(dos,'\0',sizeof(Dosdisc_t));
404da2e3ebdSchin 
405da2e3ebdSchin 	dos->disc.readf = dos_read;
406da2e3ebdSchin 	dos->disc.writef = NIL(Sfwrite_f);
407da2e3ebdSchin 	dos->disc.seekf = dos_seek;
408da2e3ebdSchin 	dos->disc.exceptf = dos_except;
409da2e3ebdSchin 
410da2e3ebdSchin 	if(sfdisc(f,(Sfdisc_t*)dos) != (Sfdisc_t*)dos)
411da2e3ebdSchin 	{	free(dos);
412da2e3ebdSchin 		return -1;
413da2e3ebdSchin 	}
414da2e3ebdSchin 
415da2e3ebdSchin 	return(0);
416da2e3ebdSchin }
417