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