3
/* Discipline to turn \r\n into \n.
4
** This is useful to deal with DOS text files.
6
** Written by David Korn (03/18/1998).
18
typedef struct _dosdisc
39
static void addmapping(register Dosdisc_t *dp)
41
static void addmapping(dp)
42
register Dosdisc_t *dp;
46
if((n=dp->maptop++)>=dp->mapsize)
49
if(!(dp->maptable=(struct map*)realloc((void*)dp->maptable,(dp->mapsize+1)*sizeof(struct map))))
56
dp->maptable[n].physical = dp->phere;
57
dp->maptable[n].logical = dp->lhere;
58
dp->maptable[dp->maptop].logical=0;
62
static struct map *getmapping(Dosdisc_t *dp, off_t offset, register int whence)
64
static struct map *getmapping(dp, offset, whence)
70
register struct map *mp;
71
static struct map dummy;
72
if(offset <= dp->begin)
74
dummy.logical = dummy.physical = offset;
77
if(!(mp=dp->maptable))
79
dummy.logical = dp->begin;
80
dummy.physical = dummy.logical+1;
83
while((++mp)->logical && (whence==SEEK_CUR?mp->physical:mp->logical) <= offset);
88
static ssize_t dos_read(Sfio_t *iop, void *buff, size_t size, Sfdisc_t* disc)
90
static ssize_t dos_read(iop, buff, size, disc)
97
register Dosdisc_t *dp = (Dosdisc_t*)disc;
98
register char *cp = (char*)buff, *first, *cpmax;
99
register int n, count, m;
108
if((n = sfrd(iop,buff,size,disc)) <= 0)
112
dp->llast = dp->lhere;
114
if(dp->last=='\r' && *cp!='\n')
116
/* should insert a '\r' */ ;
129
else if(dp->last!='\n' || cpmax[-1]!='\r')
134
while(*cp++ != '\r');
135
if(cp > cpmax || *cp=='\n')
138
dp->skip = cp-1 - (char*)buff;
139
/* if not \r\n in buffer, just return */
140
if((count = cpmax+1-cp) <=0)
151
dp->begin += cp - (char*)buff-1;
152
if(dp->maptable=(struct map*)malloc((MINMAP+1)*sizeof(struct map)))
154
dp->mapsize = MINMAP;
155
dp->maptable[0].logical= dp->begin;
156
dp->maptable[0].physical = dp->maptable[0].logical+1;
157
dp->maptable[1].logical=0;
161
/* save original discipline inside buffer */
165
dp->buff = malloc(count);
167
dp->buff = realloc(dp->buff,count);
172
memcpy(dp->buff, cp, count);
180
while(*cp++ != '\r');
181
if(cp<=cpmax && *cp!='\n')
183
if((m=(cp-first)-1) >0)
184
memcpy(first-count, first, m);
189
cpmax[-count] = dp->last;
192
if(dp->lhere>dp->lmax)
194
dp->lmax = dp->lhere;
195
dp->pmax = dp->phere;
196
if(dp->maptable && dp->lmax > dp->maptable[dp->maptop-1].logical+CHUNK)
203
* returns the current offset
204
* <offset> must be in the current buffer
205
* if <whence> is SEEK_CUR, physical offset converted to logical offset
206
* otherwise, logical offset is converted to physical offset
209
static off_t cur_offset(Dosdisc_t *dp, off_t offset,Sfio_t *iop,register int whence)
211
static off_t cur_offset(dp, offset, iop, whence)
218
register off_t n,m=0;
224
n = offset - dp->plast;
225
iop->next = iop->data + n;
231
n = offset - dp->llast;
235
if((n -= dp->skip) > 0)
238
cp = (char*)dp->buff;
241
if(*cp++=='\r' && *cp=='\n')
255
static Sfoff_t dos_seek(Sfio_t *iop, Sfoff_t offset, register int whence, Sfdisc_t* disc)
257
static Sfoff_t dos_seek(iop, offset, whence, disc)
264
register Dosdisc_t *dp = (Dosdisc_t*)disc;
265
struct map dummy, *mp=0;
272
offset = sfsk(iop, (off_t)0,SEEK_CUR,disc);
273
if(offset<=dp->begin)
275
/* check for seek outside buffer */
276
if(offset==dp->phere)
278
else if(offset==dp->plast)
280
else if(offset<dp->plast || offset>dp->phere)
281
mp = getmapping(dp,offset,whence);
284
/* check for seek outside buffer */
285
if(offset<dp->llast || offset > dp->lhere)
286
mp = getmapping(dp,offset,whence);
290
return(sfsk(iop,offset,SEEK_END,disc));
292
mp->physical = dp->plast;
293
mp->logical = dp->llast;
296
if(sfsetbuf(iop,(char*)iop,0))
299
size = iop->endb-iop->data;
302
sfsk(iop,mp->physical,SEEK_SET,disc);
303
dp->phere = mp->physical;
304
dp->lhere = mp->logical;
305
if((*disc->readf)(iop,iop->data,size,disc)<0)
310
if(whence==SEEK_CUR && dp->phere>=offset)
312
if(whence==SEEK_SET && dp->lhere>=offset)
314
n=(*disc->readf)(iop,iop->data,size,disc);
319
if(whence==SEEK_END && offset<0)
332
physical = cur_offset(dp,offset,iop,whence);
335
sfsk(iop, physical ,SEEK_SET,disc);
336
dp->phere = physical;
346
static int dos_except(Sfio_t *iop, int type, void *arg, Sfdisc_t *disc)
348
static int dos_except(iop, type, arg, disc)
355
register Dosdisc_t *dp = (Dosdisc_t*)disc;
356
if(type==SF_DPOP || type==SF_FINAL)
359
free((void*)dp->buff);
361
free((void*)dp->maptable);
368
int sfdcdos(Sfio_t *f)
376
/* this is a readonly discipline */
377
if(sfset(f,0,0)&SF_WRITE)
380
if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) )
382
memset(dos,'\0',sizeof(Dosdisc_t));
384
dos->disc.readf = dos_read;
385
dos->disc.writef = NIL(Sfwrite_f);
386
dos->disc.seekf = dos_seek;
387
dos->disc.exceptf = dos_except;
389
if(sfdisc(f,(Sfdisc_t*)dos) != (Sfdisc_t*)dos)