1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 /* Discipline to turn \r\n into \n.
25 ** This is useful to deal with DOS text files.
27 ** Written by David Korn (03/18/1998).
39 typedef struct _dosdisc
60 static void addmapping(register Dosdisc_t
*dp
)
62 static void addmapping(dp
)
63 register Dosdisc_t
*dp
;
67 if((n
=dp
->maptop
++)>=dp
->mapsize
)
70 if(!(dp
->maptable
=(struct map
*)realloc((void*)dp
->maptable
,(dp
->mapsize
+1)*sizeof(struct map
))))
77 dp
->maptable
[n
].physical
= dp
->phere
;
78 dp
->maptable
[n
].logical
= dp
->lhere
;
79 dp
->maptable
[dp
->maptop
].logical
=0;
83 static struct map
*getmapping(Dosdisc_t
*dp
, Sfoff_t offset
, register int whence
)
85 static struct map
*getmapping(dp
, offset
, whence
)
91 register struct map
*mp
;
92 static struct map dummy
;
93 if(offset
<= dp
->begin
)
95 dummy
.logical
= dummy
.physical
= offset
;
98 if(!(mp
=dp
->maptable
))
100 dummy
.logical
= dp
->begin
;
101 dummy
.physical
= dummy
.logical
+1;
104 while((++mp
)->logical
&& (whence
==SEEK_CUR
?mp
->physical
:mp
->logical
) <= offset
);
109 static ssize_t
dos_read(Sfio_t
*iop
, void *buff
, size_t size
, Sfdisc_t
* disc
)
111 static ssize_t
dos_read(iop
, buff
, size
, disc
)
118 register Dosdisc_t
*dp
= (Dosdisc_t
*)disc
;
119 register char *cp
= (char*)buff
, *first
, *cpmax
;
120 register int n
, count
, m
;
129 if((n
= sfrd(iop
,buff
,size
,disc
)) <= 0)
133 dp
->llast
= dp
->lhere
;
135 if(dp
->last
=='\r' && *cp
!='\n')
137 /* should insert a '\r' */ ;
150 else if(dp
->last
!='\n' || cpmax
[-1]!='\r')
155 while(*cp
++ != '\r');
156 if(cp
> cpmax
|| *cp
=='\n')
159 dp
->skip
= cp
-1 - (char*)buff
;
160 /* if not \r\n in buffer, just return */
161 if((count
= cpmax
+1-cp
) <=0)
172 dp
->begin
+= cp
- (char*)buff
-1;
173 if(dp
->maptable
=(struct map
*)malloc((MINMAP
+1)*sizeof(struct map
)))
175 dp
->mapsize
= MINMAP
;
176 dp
->maptable
[0].logical
= dp
->begin
;
177 dp
->maptable
[0].physical
= dp
->maptable
[0].logical
+1;
178 dp
->maptable
[1].logical
=0;
182 /* save original discipline inside buffer */
186 dp
->buff
= malloc(count
);
188 dp
->buff
= realloc(dp
->buff
,count
);
193 memcpy(dp
->buff
, cp
, count
);
201 while(*cp
++ != '\r');
202 if(cp
<=cpmax
&& *cp
!='\n')
204 if((m
=(cp
-first
)-1) >0)
205 memcpy(first
-count
, first
, m
);
210 cpmax
[-count
] = dp
->last
;
213 if(dp
->lhere
>dp
->lmax
)
215 dp
->lmax
= dp
->lhere
;
216 dp
->pmax
= dp
->phere
;
217 if(dp
->maptable
&& dp
->lmax
> dp
->maptable
[dp
->maptop
-1].logical
+CHUNK
)
224 * returns the current offset
225 * <offset> must be in the current buffer
226 * if <whence> is SEEK_CUR, physical offset converted to logical offset
227 * otherwise, logical offset is converted to physical offset
230 static Sfoff_t
cur_offset(Dosdisc_t
*dp
, Sfoff_t offset
,Sfio_t
*iop
,register int whence
)
232 static Sfoff_t
cur_offset(dp
, offset
, iop
, whence
)
239 register Sfoff_t n
,m
=0;
245 n
= offset
- dp
->plast
;
246 iop
->next
= iop
->data
+ n
;
252 n
= offset
- dp
->llast
;
256 if((n
-= dp
->skip
) > 0)
259 cp
= (char*)dp
->buff
;
262 if(*cp
++=='\r' && *cp
=='\n')
276 static Sfoff_t
dos_seek(Sfio_t
*iop
, Sfoff_t offset
, register int whence
, Sfdisc_t
* disc
)
278 static Sfoff_t
dos_seek(iop
, offset
, whence
, disc
)
285 register Dosdisc_t
*dp
= (Dosdisc_t
*)disc
;
286 struct map dummy
, *mp
=0;
293 offset
= sfsk(iop
, (Sfoff_t
)0,SEEK_CUR
,disc
);
294 if(offset
<=dp
->begin
)
296 /* check for seek outside buffer */
297 if(offset
==dp
->phere
)
299 else if(offset
==dp
->plast
)
301 else if(offset
<dp
->plast
|| offset
>dp
->phere
)
302 mp
= getmapping(dp
,offset
,whence
);
305 /* check for seek outside buffer */
306 if(offset
<dp
->llast
|| offset
> dp
->lhere
)
307 mp
= getmapping(dp
,offset
,whence
);
311 return(sfsk(iop
,offset
,SEEK_END
,disc
));
313 mp
->physical
= dp
->plast
;
314 mp
->logical
= dp
->llast
;
317 if(sfsetbuf(iop
,(char*)iop
,0))
320 size
= iop
->endb
-iop
->data
;
323 sfsk(iop
,mp
->physical
,SEEK_SET
,disc
);
324 dp
->phere
= mp
->physical
;
325 dp
->lhere
= mp
->logical
;
326 if((*disc
->readf
)(iop
,iop
->data
,size
,disc
)<0)
331 if(whence
==SEEK_CUR
&& dp
->phere
>=offset
)
333 if(whence
==SEEK_SET
&& dp
->lhere
>=offset
)
335 n
=(*disc
->readf
)(iop
,iop
->data
,size
,disc
);
340 if(whence
==SEEK_END
&& offset
<0)
353 physical
= cur_offset(dp
,offset
,iop
,whence
);
356 sfsk(iop
, physical
,SEEK_SET
,disc
);
357 dp
->phere
= physical
;
367 static int dos_except(Sfio_t
*iop
, int type
, void *arg
, Sfdisc_t
*disc
)
369 static int dos_except(iop
, type
, arg
, disc
)
376 register Dosdisc_t
*dp
= (Dosdisc_t
*)disc
;
377 if(type
==SF_DPOP
|| type
==SF_FINAL
)
380 free((void*)dp
->buff
);
382 free((void*)dp
->maptable
);
389 int sfdcdos(Sfio_t
*f
)
397 /* this is a readonly discipline */
398 if(sfset(f
,0,0)&SF_WRITE
)
401 if(!(dos
= (Dosdisc_t
*)malloc(sizeof(Dosdisc_t
))) )
403 memset(dos
,'\0',sizeof(Dosdisc_t
));
405 dos
->disc
.readf
= dos_read
;
406 dos
->disc
.writef
= NIL(Sfwrite_f
);
407 dos
->disc
.seekf
= dos_seek
;
408 dos
->disc
.exceptf
= dos_except
;
410 if(sfdisc(f
,(Sfdisc_t
*)dos
) != (Sfdisc_t
*)dos
)